update readme and tests
This commit is contained in:
parent
c17a7b98b6
commit
b6ee6d3ce2
158
README.md
158
README.md
@ -5,6 +5,18 @@ self-signed CA.
|
||||
|
||||
## Purpose
|
||||
|
||||
The whole idea is to run the ``gencert.sh`` script right before starting the
|
||||
service and then, making sure the reverse proxy updates its main CA bundle
|
||||
right before starting.
|
||||
|
||||
Some services require the certificate on their backend and would not be
|
||||
satisfied with the TLS termination elsewhere.
|
||||
|
||||
For example, one of such services is Minio. It [requires](https://github.com/minio/minio/issues/6093) its certificate in order
|
||||
to enable SSE-C (Server Side Encryption with Customer provided keys).
|
||||
|
||||
## How does this script work
|
||||
|
||||
This script will always produce a self-signed x509 certificate with the IP
|
||||
addresses embedded to x509's SAN.
|
||||
|
||||
@ -14,121 +26,75 @@ which may need to authenticate against this self-signed certificate.
|
||||
The authentication works in a way that a public CA certificate will be
|
||||
used by the client in order to validate the server's certificate.
|
||||
|
||||
## Application
|
||||
|
||||
### Backend requiring x509 running behind reverse proxy
|
||||
|
||||
This script has been created in order to ease the Minio's SSE-C
|
||||
(Server Side Encryption - Customer provided keys) enablement when
|
||||
Minio server is running as a backend behind a reverse proxy like Traefik.
|
||||
|
||||
Minio server enables SSE-C only when it detects the x509 certificates.
|
||||
|
||||
Traefik (running with docker service provider or similar) is talking to the
|
||||
backend using the IP address rather than a hostname.
|
||||
|
||||
Usually, the IP address is not static, hence this script comes handy.
|
||||
|
||||
## Script logic
|
||||
|
||||
- generate CA certificate if does not find any
|
||||
- always generate server certificate on startup to ensure all IP addresses
|
||||
are in x509 SAN
|
||||
- warn if the CA certificate is about to expire (<30 days till expiration)
|
||||
- regenerate the CA certificate if it finds it has expired
|
||||
|
||||
## Notes
|
||||
> - The CA certificate will be valid for 3650 days (10 years)
|
||||
> - The server certifcate will be valid for 365 days (1 year)
|
||||
> - The x509 certs are ECDSA with prime256v1 curve and SHA256 signatures
|
||||
|
||||
- The CA certificate will be valid for 3650 days (10 years)
|
||||
- The server certifcate will be valid for 365 days (1 year)
|
||||
- The x509 certs are ECDSA with prime256v1 curve and SHA256 signatures
|
||||
## Examples
|
||||
|
||||
### Minio and Docker Registry services with Traefik reverse proxy
|
||||
|
||||
- docker-compose.yml
|
||||
|
||||
> I intentionally left only the gencert-related lines.
|
||||
>
|
||||
> If you are using Alpine based image, the correct CA certificates path is
|
||||
> ``/usr/local/share/ca-certificates/``, otherwise one of these
|
||||
> https://golang.org/src/crypto/x509/root_linux.go
|
||||
|
||||
```
|
||||
services:
|
||||
minio:
|
||||
image: minio/minio
|
||||
volumes:
|
||||
- /srv/data/minio/certs:/root/.minio/certs
|
||||
- /srv/services/gencert/gencert.sh:/gencert.sh:ro
|
||||
entrypoint: sh -c "cd /root/.minio/certs && /gencert.sh --cn minio.example.com && minio server /data"
|
||||
environment:
|
||||
- "MINIO_ACCESS_KEY=redacted"
|
||||
- "MINIO_SECRET_KEY=redacted"
|
||||
|
||||
registry:
|
||||
image: registry:2.6.2
|
||||
volumes:
|
||||
- /srv/services/gencert/gencert.sh:/gencert.sh:ro
|
||||
- /srv/data/registry/certs:/certs
|
||||
entrypoint: sh -c "cd /certs && /gencert.sh --cn registry.example.com && registry serve /etc/docker/registry/config.yml"
|
||||
environment:
|
||||
REGISTRY_HTTP_TLS_CERTIFICATE: '/certs/public.crt'
|
||||
REGISTRY_HTTP_TLS_KEY: '/certs/private.key'
|
||||
|
||||
traefik:
|
||||
image: traefik:1.6-alpine
|
||||
volumes:
|
||||
- /srv/data/minio/certs/ca.crt:/usr/local/share/ca-certificates/minio_ca.crt:ro
|
||||
- /srv/data/registry/certs/ca.crt:/usr/local/share/ca-certificates/registry_ca.crt:ro
|
||||
command: sh -c "update-ca-certificates && traefik"
|
||||
depends_on:
|
||||
- minio
|
||||
- registry
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
I have added a simplistic script [testme.sh](testme.sh) that helps to test this
|
||||
script in the following Linux distributions:
|
||||
|
||||
- Alpine 3.4
|
||||
- Alpine 3.7
|
||||
- Ubuntu Bionic
|
||||
- Debian Stretch
|
||||
- CentOS 7
|
||||
|
||||
## Usage example
|
||||
> Alpine 3.4 - as it has old getent which [misses](https://git.alpinelinux.org/cgit/aports/commit/?id=2e4493888fff74afc6a6ef6257aeea469df32af5) ahostsv4
|
||||
|
||||
### Minio server with Traefik example
|
||||
|
||||
1. Replace ``minio server`` command with the following one:
|
||||
``cd /root/.minio/certs && ./gencert.sh --cn minio.example.com && minio server /data``
|
||||
2. Copy the CA certificate ``ca.crt`` file to ``/usr/local/share/ca-certificates/`` and
|
||||
run ``update-ca-certificates`` command which will update
|
||||
``/etc/ssl/certs/ca-certificates.crt`` file;
|
||||
3. Restart Traefik.
|
||||
|
||||
With the Step 1. Minio server will get the certificate it needs, hence SSE-C
|
||||
will be enabled.
|
||||
|
||||
Steps 2. and 3. will need to be repeated each time you get a new CA
|
||||
certificate.
|
||||
These steps can be automated this way:
|
||||
Start Traefik with this command:
|
||||
``sh -c "update-ca-certificates && traefik"``
|
||||
while ``/usr/local/share/ca-certificates`` container path is mounted from the
|
||||
host with the CA certificate produced by this script.
|
||||
|
||||
I am using Alpine Traefik image, the correct ca certificates path is
|
||||
``/usr/local/share/ca-certificates/``, otherwise one of these
|
||||
https://golang.org/src/crypto/x509/root_linux.go
|
||||
|
||||
- ``docker-compose.yml`` example with the gencert script:
|
||||
|
||||
```
|
||||
version: '3'
|
||||
|
||||
networks:
|
||||
oasis: {}
|
||||
|
||||
services:
|
||||
minio:
|
||||
restart: unless-stopped
|
||||
image: minio/minio
|
||||
networks:
|
||||
- oasis
|
||||
volumes:
|
||||
- /srv/data/minio:/data
|
||||
- /srv/data/minio/start/gencert.sh:/gencert.sh:ro
|
||||
entrypoint: sh -c "cd /root/.minio/certs && /gencert.sh --cn minio.example.com && minio server /data"
|
||||
environment:
|
||||
- "MINIO_ACCESS_KEY=redacted"
|
||||
- "MINIO_SECRET_KEY=redacted"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.frontend.rule=Host: minio.example.com"
|
||||
- "traefik.frontend.passHostHeader=true"
|
||||
- "traefik.port=9000"
|
||||
|
||||
traefik:
|
||||
restart: unless-stopped
|
||||
image: traefik:1.6-alpine
|
||||
volumes:
|
||||
- /srv/data/traefik/acme:/etc/traefik/acme
|
||||
- /srv/data/traefik/traefik.toml:/etc/traefik/traefik.toml:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro # listen to the Docker events.
|
||||
- /srv/data/traefik/ca-certs:/usr/local/share/ca-certificates:ro
|
||||
command: sh -c "update-ca-certificates && traefik"
|
||||
networks:
|
||||
- oasis
|
||||
ports:
|
||||
- "127.0.0.1:8080:8080"
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
```
|
||||
|
||||
### Drawbacks
|
||||
## Drawbacks
|
||||
|
||||
- [operational] it requires self-signed CA certs shared when running multiple
|
||||
Minio (or any other) servers;
|
||||
- [operational] every X years it requires updating the CA certificate in the
|
||||
Traefik's (or any other reverse proxy) container;
|
||||
- [security] the CA key will have to be spread all over the environment.
|
||||
Theoretically, this could be solved by HashiCorp's Vault, but that won't be
|
||||
nice & small way of running things;
|
||||
|
@ -5,7 +5,7 @@ TMPDIR="$(mktemp -d)"
|
||||
cp -v gencert.sh "${TMPDIR}/"
|
||||
pushd "${TMPDIR}"
|
||||
|
||||
for DISTRO in alpine:3.7 ubuntu:bionic debian:stretch centos:7; do
|
||||
for DISTRO in alpine:3.4 alpine:3.7 ubuntu:bionic debian:stretch centos:7; do
|
||||
printf "\n\n\nTesting the script with ${DISTRO} ...\n\n\n"
|
||||
rm -vf openssl.cnf private.key public.crt ca.crt ca.key ca.srl
|
||||
docker run --rm -ti -v ${PWD}:/w -w /w ${DISTRO} sh gencert.sh --cn test.example.com
|
||||
|
Loading…
Reference in New Issue
Block a user