update readme and tests

master
Andy 6 years ago
parent c17a7b98b6
commit b6ee6d3ce2
Signed by: arno
GPG Key ID: 9076D5E6B31AE99C

@ -5,6 +5,18 @@ self-signed CA.
## Purpose ## 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 This script will always produce a self-signed x509 certificate with the IP
addresses embedded to x509's SAN. 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 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. 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 - generate CA certificate if does not find any
- always generate server certificate on startup to ensure all IP addresses - always generate server certificate on startup to ensure all IP addresses
are in x509 SAN are in x509 SAN
- warn if the CA certificate is about to expire (<30 days till expiration) - warn if the CA certificate is about to expire (<30 days till expiration)
- regenerate the CA certificate if it finds it has expired - 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) ## Examples
- The server certifcate will be valid for 365 days (1 year)
- The x509 certs are ECDSA with prime256v1 curve and SHA256 signatures
## Testing
I have added a simplistic script [testme.sh](testme.sh) that helps to test this
script in the following Linux distributions:
- Alpine 3.7
- Ubuntu Bionic
- Debian Stretch
- CentOS 7
## Usage example ### Minio and Docker Registry services with Traefik reverse proxy
### Minio server with Traefik example - docker-compose.yml
1. Replace ``minio server`` command with the following one: > I intentionally left only the gencert-related lines.
``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 > If you are using Alpine based image, the correct CA certificates path is
run ``update-ca-certificates`` command which will update > ``/usr/local/share/ca-certificates/``, otherwise one of these
``/etc/ssl/certs/ca-certificates.crt`` file; > https://golang.org/src/crypto/x509/root_linux.go
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: services:
minio: minio:
restart: unless-stopped
image: minio/minio image: minio/minio
networks:
- oasis
volumes: volumes:
- /srv/data/minio:/data - /srv/data/minio/certs:/root/.minio/certs
- /srv/data/minio/start/gencert.sh:/gencert.sh:ro - /srv/services/gencert/gencert.sh:/gencert.sh:ro
entrypoint: sh -c "cd /root/.minio/certs && /gencert.sh --cn minio.example.com && minio server /data" entrypoint: sh -c "cd /root/.minio/certs && /gencert.sh --cn minio.example.com && minio server /data"
environment: environment:
- "MINIO_ACCESS_KEY=redacted" - "MINIO_ACCESS_KEY=redacted"
- "MINIO_SECRET_KEY=redacted" - "MINIO_SECRET_KEY=redacted"
labels:
- "traefik.enable=true" registry:
- "traefik.frontend.rule=Host: minio.example.com" image: registry:2.6.2
- "traefik.frontend.passHostHeader=true" volumes:
- "traefik.port=9000" - /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: traefik:
restart: unless-stopped
image: traefik:1.6-alpine image: traefik:1.6-alpine
volumes: volumes:
- /srv/data/traefik/acme:/etc/traefik/acme - /srv/data/minio/certs/ca.crt:/usr/local/share/ca-certificates/minio_ca.crt:ro
- /srv/data/traefik/traefik.toml:/etc/traefik/traefik.toml:ro - /srv/data/registry/certs/ca.crt:/usr/local/share/ca-certificates/registry_ca.crt: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" command: sh -c "update-ca-certificates && traefik"
networks: depends_on:
- oasis - minio
ports: - registry
- "127.0.0.1:8080:8080"
- "80:80"
- "443:443"
``` ```
### Drawbacks ## 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
> Alpine 3.4 - as it has old getent which [misses](https://git.alpinelinux.org/cgit/aports/commit/?id=2e4493888fff74afc6a6ef6257aeea469df32af5) ahostsv4
## Drawbacks
- [operational] it requires self-signed CA certs shared when running multiple - [operational] it requires self-signed CA certs shared when running multiple
Minio (or any other) servers; 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}/" cp -v gencert.sh "${TMPDIR}/"
pushd "${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" 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 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 docker run --rm -ti -v ${PWD}:/w -w /w ${DISTRO} sh gencert.sh --cn test.example.com

Loading…
Cancel
Save