You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
4.9 KiB
138 lines
4.9 KiB
# gencert
|
|
|
|
This script generates x509 server certificate (with all IPs in SAN) signed by a
|
|
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.
|
|
|
|
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.
|
|
|
|
- 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
|
|
|
|
> 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 behind 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
|
|
```
|
|
|
|
### helloworld with socat
|
|
|
|
socat could be handy when you need to see the TLS flow between the reverse
|
|
proxy and a backend.
|
|
|
|
It may also help you secure the traffic between the reverse proxy and a backend
|
|
in case when the latter service does not support TLS on its own.
|
|
|
|
> Minimum socat version should be [1.7.3.2](https://fossies.org/linux/privat/socat-1.7.3.2.tar.gz/socat-1.7.3.2/CHANGES) so it will work with the
|
|
> ECDHE- OpenSSL ciphers.
|
|
|
|
```
|
|
services:
|
|
helloworld:
|
|
image: dockercloud/hello-world
|
|
volumes:
|
|
- /srv/services/gencert/gencert.sh:/gencert.sh:ro
|
|
entrypoint: sh -c "mkdir /certs && cd /certs &&
|
|
/gencert.sh --cn helloworld &&
|
|
( nohup /run.sh & ) &&
|
|
echo '@edge http://nl.alpinelinux.org/alpine/edge/main' | tee -a /etc/apk/repositories &&
|
|
apk --update add socat@edge &&
|
|
socat -v -v -d -d OPENSSL-LISTEN:443,reuseaddr,verify=0,cafile=./ca.crt,cert=./public.crt,key=./private.key,fork TCP4-CONNECT:127.0.0.1:80"
|
|
labels:
|
|
traefik.enable: 'true'
|
|
traefik.frontend.rule: 'Host: hello.example.com'
|
|
traefik.frontend.entryPoints: 'http,https'
|
|
traefik.backend.loadbalancer.stickiness: 'true'
|
|
traefik.port: '443'
|
|
traefik.protocol: 'https'
|
|
```
|
|
|
|
If you get ``sslv3 alert bad certificate`` error, then make sure you have
|
|
either updated the CA bundle with your CA file which was used to sign your x509
|
|
certificates at the reverse proxy server or disable TLS verification between
|
|
the reverse proxy and your backend (e.g. Traefik has a global option
|
|
``insecureSkipVerify = true``)
|
|
|
|
## 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
|