135 lines
4.3 KiB
Markdown
135 lines
4.3 KiB
Markdown
# gencert
|
|
|
|
This script generates x509 server certificate (with all IPs in SAN) signed by a
|
|
self-signed CA.
|
|
|
|
## Purpose
|
|
|
|
This script will always produce a self-signed x509 certificate with the IP
|
|
addresses embedded to x509's SAN.
|
|
|
|
It will also produce a CA certificate and can be used by other services
|
|
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
|
|
|
|
## 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 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
|
|
|
|
- [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;
|