Skip to content

Commit

Permalink
Document custom ssl certificate (#404)
Browse files Browse the repository at this point in the history
* Add documentation for custom SSL certificates

* typo: localstck

* Ignore localhost.localstack.cloud link in updated doc

Signed-off-by: Simon Walker <simon.walker@localstack.cloud>

* Document init hooks

* swap CURL_CA_BUNDLE -> REQUESTS_CA_BUNDLE

We perform checks if the user has set this, and enforce SSL verification
so we should probably ask them to use that.

* Document windows host mode with WSL2

* Document CURL_CA_BUNDLE as well

* include tab pane for running localstack

* Link from init hook examples to custom SSL certificates

* Rename SSL -> TLS

* Correct typo

* update tldr with curl updates

Signed-off-by: Simon Walker <simon.walker@localstack.cloud>
  • Loading branch information
simonrw committed Dec 15, 2022
1 parent acbece1 commit 156be24
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .github/workflows/markdown.links.config.json
Expand Up @@ -26,6 +26,9 @@
},
{
"pattern": "http://localstack:4566"
},
{
"pattern": "(.*)localhost.localstack.cloud(.*)"
}
],
"httpHeaders": [
Expand Down
130 changes: 130 additions & 0 deletions content/en/references/custom-tls-certificates.md
@@ -0,0 +1,130 @@
---
title: Custom TLS certificates
weight: 99
tags:
- ssl
description: >
How to use custom TLS certificates with LocalStack
---

# Background

LocalStack sometimes performs on-demand fetching of resources from the public internet.
This requires that LocalStack is able to access public URLs.
If there is a proxy server in your network that uses a non-standard TLS certificate, LocalStack will not be able to download any files on demand.
You may see errors in the logs relating to TLS such as "unable to get local issuer certificate".

# Solution

There are three options when running LocalStack:

1. [creating a custom Docker image]({{< ref "#creating-a-custom-docker-image" >}}),
2. [using init hooks]({{< ref "#custom-ssl-certificates-with-init-hooks" >}}) or
3. [when running in host mode]({{< ref "#custom-ssl-certificates-with-host-mode" >}}).

They all can be summarised as:

1. get your proxy's custom certificate into the system certificate store, and
2. configure [`requests`](https://pypi.python.org/pypi/requests) to use the custom certificate, and
3. configure [`curl`](https://curl.se/) to use the custom certificate.

## Creating a custom docker image

If you run LocalStack in a docker container (which includes using [the CLI]({{< ref "/getting-started#localstack-cli" >}}), [docker]({{< ref "/getting-started/#docker" >}}), [docker-compose]({{< ref "/getting-started/#docker-compose" >}}), [cockpit]({{< ref "/getting-started/#localstack-cockpit" >}}) or [helm]({{< ref "/getting-started/#helm" >}})), to include a custom TLS root certificate a new docker image should be created.

Create a `Dockerfile` containing the following commands:

```docker
FROM localstack/localstack:latest
# or if using the pro image:
FROM localstack/localstack-pro:latest
COPY <your custom certificate.crt> /usr/local/share/ca-certificates/cert-bundle.crt
RUN update-ca-certificates
ENV CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
ENV REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
```

and build the image:

{{< command >}}
$ docker build -t <image name> .
{{< / command >}}

{{< alert title="Information" color="primary">}}
**Note**: Certificate files **must** end in `.crt` to be included in the system certificate store.
If your certificate file ends with `.pem`, you can rename it to end in `.crt`.
{{< / alert>}}

### Starting LocalStack with the custom image

LocalStack now needs to be configured to use this custom image. The workflow is different depending on how you start localstack.

{{< tabpane >}}
{{< tab header="CLI" lang="bash" >}}
IMAGE_NAME=<image name> localstack start
{{< /tab >}}
{{< tab header="Docker" lang="bash" >}}
docker run <docker arguments> <image name>
{{< /tab >}}
{{< tab header="docker-compose.yml" lang="yml" >}}
services:
localstack:
image: <image name>
# the rest of your configuration
{{< /tab >}}
{{< / tabpane >}}

## Custom TLS certificates with init hooks

It is recommended to create a `boot` init hook. Create a directory on your local system that includes

* the certificate you wish to copy, and
* the following shell script:

```bash
#!/bin/bash

set -euo pipefail

cp /etc/localstack/init/boot.d/<your certificate file>.crt /usr/local/share/ca-certificates
update-ca-certificates
```

Then run LocalStack with the environment variables

* `REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt`, and
* `CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt`, and

and follow the instructions fn the [init hooks documentation]({{< ref "init-hooks" >}}) for configuring LocalStack to use the hook directory as a `boot` hook.

## Custom TLS certificates with host mode

### Linux

On linux the custom certificate should be added to your `ca-certificates` bundle. For example on Debian based systems (as root):

{{< command >}}
# cp <your custom certificate.crt> /usr/local/share/ca-certificates
# update-ca-certificates
{{< / command >}}

Then run LocalStack with the environment variables `REQUESTS_CA_BUNDLE` and `CURL_CA_BUNDLE`:

{{< command >}}
$ CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt localstack start --host
{{< / command >}}

### macos

On macos the custom certificate should be added to your keychain. See [this Apple support article](https://support.apple.com/en-gb/guide/keychain-access/kyca2431/mac) for more information.

Then run LocalStack with the environment variables `REQUESTS_CA_BUNDLE` and `CURL_CA_BUNDLE`:

{{< command >}}
$ CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt localstack start --host
{{< / command >}}

### Windows

Currently host mode does not work with Windows. If you are using WSL2 you should follow the [Linux]({{< ref "#linux" >}}) steps above.
2 changes: 2 additions & 0 deletions content/en/references/init-hooks.md
Expand Up @@ -146,3 +146,5 @@ services:
DOCKER_FLAGS='-v /path/to/init-aws.sh:/etc/localstack/init/ready.d/init-aws.sh' localstack start
{{< /tab >}}
{{< /tabpane >}}

Another use for init hooks can be seen when [adding custom TLS certificates to LocalStack]({{< ref "custom-tls-certificates#custom-tls-certificates-with-init-hooks" >}}).
Expand Up @@ -12,7 +12,7 @@ You can configure the local endpoint URL under which LocalStack is accessible fr

## Connecting to a LocalStack instance on a different machine

To ensure that the Web user interface can connect with your running LocalStck instance, you would need to configure the endpoint URL so that the server's SSL certificate matches the hostname/IP address of the endpoint URL. This situation arises when users configure the endpoint URL to be something like `https://myhost:4566` or use an IP address like `https://1.2.3.4:4566`. Websites with an `https://...` URL can only request other endpoints using HTTPS (i.e., not on `http://`). Additionally, while requesting an HTTPS page, the SSL certificate must match the hostname (i.e., `localhost.localstack.cloud` in our case).
To ensure that the Web user interface can connect with your running LocalStack instance, you would need to configure the endpoint URL so that the server's SSL certificate matches the hostname/IP address of the endpoint URL. This situation arises when users configure the endpoint URL to be something like `https://myhost:4566` or use an IP address like `https://1.2.3.4:4566`. Websites with an `https://...` URL can only request other endpoints using HTTPS (i.e., not on `http://`). Additionally, while requesting an HTTPS page, the SSL certificate must match the hostname (i.e., `localhost.localstack.cloud` in our case).

To navigate this, we recommend you create a local TCP proxy server. The proxy server could listen on `127.0.0.1:4566` and forward all requests to your target endpoint where the LocalStack instance is running. You could leave the configuration in the Web user interface to use the default value, `https://localhost.localstack.cloud:4566`. We recommend [simpleproxy](https://manpages.ubuntu.com/manpages/trusty/man1/simpleproxy.1.html) or [proxy.py](https://github.com/abhinavsingh/proxy.py) as a way to implement this.

Expand Down

0 comments on commit 156be24

Please sign in to comment.