Self-Signed Certificates for traefik

Self-Signed Certificates for traefik

Objective

Create self-signed certificates that can be used by traefik within a docker-compose stack. The certificates should be used to test a SSL/TLS connection i.e to check if the configuration is working as expected.

Context

  • Raspberry Pi 4 B (RAM: 4 GBytes,  SSD: 128 GBytes)
  • Raspbian Buster Desktop (Release: February 2020, Kernel: 4.19)
  • Docker version 19.03.8 & Docker-Compose version 1.25.4
  • traefik verion 2.2.0 (Release: March 2020)

How-to

traefik is able to handle with certificates to enable and secure SSL/TLS connections to services (e.g. web server) exposed by a docker environment. A self-signed certificate can be used to validate this kind of setup in a "local" context (e.g. localhost). Different use cases may be considered:

Use-Case 1: Certificate for a single domain

Each domain i.e. each service reachable per SSL/TLS connection is using its own specific certificate (e.g. 1 x "localhost" and 1 x "raspberrypi").

1) create the bare certificate files in the traefik certificate repository (directory)

$ openssl req -x509 -newkey rsa:4096 -keyout localhost.key \
-out localhost.crt -days 365 -nodes
$ openssl req -x509 -newkey rsa:4096 -keyout raspberrypi.key \
-out raspberrypi.crt -days 365 -nodes
$
generate a self-signed certificate for the "localhost" and "raspberrypi" domain

Note: when asked to enter a common name, use 'localhost' and 'raspberrypi' for the two certificates above.
The first certificate can be used internally within your server for example for testing purpose. The second certificate allows to test the SSL/TLS within your LAN (replace "raspberrypi" above with the name of your server).

2) change the access permissions on the bare files (for the sake of system security)

$ chmod 644 *.crt
$ chmod 600 *.key
$ 
restrict access permissions on the certificate files

3) check the access permissions modifications (optional) in the directory containing the certificates

$ find $1 -type f,d -print0 | xargs -0 stat \
--format '[%a][%A] %n' | sort -nr | head
[755][drwxr-xr-x] .
[644][-rw-r--r--] ./raspberrypi.crt
[644][-rw-r--r--] ./localhost.crt
[600][-rw-------] ./raspberrypi.key
[600][-rw-------] ./localhost.key
$ 
check access permissions

It is important to note, that those self-signed certificates should not be DES encrypted, hence the usage of the flag -nodes (read: "no DES") in the OpenSSL scripts above.
Otherwise, traefik will not be able to import the certificates: traefik "unattended" import is not able to decrypt the certificates because the pass phrase is missing (and cannot be provided) .

Use-Case 2: Certificate for domain combinations (primary domain + SANs)

Many services may share a common certificate containing all required domain keys.
To demonstrate this use case, the required certificate should cover both the domains "localhost" and "whoami.localhost". Latest will be registered as a SAN (Subject Alternative Name) of the first.

Since this kind of use case is requiring a lot of data to be implemented, the choosen solution is making use of a configuration file to gather all required information & most of the parameters. A real configuration can be easily generated from the template below: one just need to adapt the list of subject_alternative_names as required.

1) Write/adapt the configuration options for OpenSSL in the following file - in particular in the "dn" and "subject_alternative_names" sections

[req]
default_bits=4096
prompt=no
default_md=sha256
x509_extensions=v3_ca
distinguished_name=dn

[dn]
C=DE
ST=Bavaria
L=Munich
O=My Raspi is my castle
CN=localhost

[v3_ca]
subjectAltName=@subject_alternative_names
keyUsage=digitalSignature, keyEncipherment
extendedKeyUsage=serverAuth

[subject_alternative_names]
DNS.1=localhost
DNS.2=whoami.localhost
Content of the file "localhost.certificate.openssl.config"

2) create the certificate using the OpenSLL configuration file above

$ openssl req -new -x509 -newkey rsa:4096 -sha256 -nodes -keyout \
localhost.key -days 365 -out localhost.crt -config \
localhost.certificate.openssl.config
$
generate the configured multi-domains certificate

3) secure the certificate as in the use-case 1 above

Conclusion

  • the objective has been attained
  • the second use case i.e. the creation of a certificate for "multiple domains" is more like a "all-in-one" strategy and offers the advantage of a configuration which can be persisted easily using a VCS (version control system) like Git, Bitbucket etc.
    It may reduce the overhead of maintaining/managing numerous certificates.
  • though it increase the dependencies between services sharing the same certificate and also complicate the operational and infrastructure related changes e.g. in case of a certificate revocation etc.
Show Comments