diff --git a/.github/workflows/markdown.links.config.json b/.github/workflows/markdown.links.config.json index 655efc73d2..96136098d8 100644 --- a/.github/workflows/markdown.links.config.json +++ b/.github/workflows/markdown.links.config.json @@ -26,6 +26,9 @@ }, { "pattern": "http://localstack:4566" + }, + { + "pattern": "(.*)localhost.localstack.cloud(.*)" } ], "httpHeaders": [ diff --git a/content/en/references/custom-tls-certificates.md b/content/en/references/custom-tls-certificates.md new file mode 100644 index 0000000000..aae2f91de6 --- /dev/null +++ b/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 /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 . +{{< / 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= localstack start +{{< /tab >}} +{{< tab header="Docker" lang="bash" >}} +docker run +{{< /tab >}} +{{< tab header="docker-compose.yml" lang="yml" >}} +services: + localstack: + image: + # 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/.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 /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. diff --git a/content/en/references/init-hooks.md b/content/en/references/init-hooks.md index 779a990265..58df241c4b 100644 --- a/content/en/references/init-hooks.md +++ b/content/en/references/init-hooks.md @@ -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" >}}). diff --git a/content/en/user-guide/web-application/custom-local-endpoint/custom-local-endpoint.md b/content/en/user-guide/web-application/custom-local-endpoint/custom-local-endpoint.md index 3135408fb0..24bb255b12 100644 --- a/content/en/user-guide/web-application/custom-local-endpoint/custom-local-endpoint.md +++ b/content/en/user-guide/web-application/custom-local-endpoint/custom-local-endpoint.md @@ -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.