Met Let’s Encrypt is het heel eenvoudig om tls-certificaten aan te vragen en automatisch te vernieuwen, maar dat is voornamelijk voor publiek toegankelijke websites. Wil je een gelijkaardige functionaliteit in je lokale netwerk, dan komt step-ca goed van pas: hiermee creëer je je eigen certificaatautoriteit, inclusief automatische vernieuwingen van certificaten.

Geschreven door: Koen Vervloesem.

Let’s Encrypt (https://letsencrypt.org/) heeft in enkele jaren tijd de industrie van certificaatautoriteiten (CA’s) overhoop gegooid. Iedereen kan nu heel eenvoudig gratis een tls-certificaat voor een domein aanvragen en automatisch via het ACME-protocol (Automatic Certificate Management Environment) vernieuwen. Dat is overigens in 2019 als RFC 8555 (https://tools.ietf.org/html/rfc8555) aangenomen.

Met Let’s Encrypt voorzie je dus heel eenvoudig je publiek toegankelijke webserver van een tls-certificaat, maar voor interne servers is het minder geschikt. Je lekt de domeinnamen waarvoor je een tls-certificaat aanvraagt immers naar internet: als onderdeel van het project Certificate Transparency (https://www.certificate-transparency.org/) worden alle uitgereikte tls-certificaten gelogd in een publiek toegankelijke database. Die kun je doorzoeken op websites van aggregators zoals https://crt.sh/ en https://censys.io/certificates. Zo krijgt iedereen een vrij goed inzicht van wat je allemaal in je interne netwerk hebt draaien.

Je eigen certificaatautoriteit

Voor interne servers draai je dus beter je eigen privé-certificaatautoriteit. Dat kan zelfs met enkele OpenSSL-opdrachten al: in feite is een certificaatautoriteit gewoon een instantie met een rootcertificaat dat andere certificaten ondertekent, en dat kun je perfect manueel. Maar voor een serieuze infrastructuur (en om fouten te vermijden) automatiseer je dat beter.

Het bedrijf smallstep (https://smallstep.com/) biedt één oplossing hiervoor aan: step-ca (https://smallstep.com/certificates/). Het programma is opensource (https://github.com/smallstep/certificates) en laat je toe om je eigen certificaatautoriteit te draaien, inclusief een server die het ACME-protocol spreekt en dus clients toelaat om net zoals bij Let’s Encrypt automatisch certificaten aan te vragen en te vernieuwen. Het verschil met Let’s Encrypt: je houdt dit alles in eigen beheer en zonder dat je informatie lekt over welke certificaten je hebt.

Installatie

Step-ca dien je op een computer te installeren die altijd toegankelijk is voor je clients. Een Linux-server die je als nas gebruikt of een Raspberry Pi is een ideale machine daarvoor. Op de GitHub-pagina van step-ca staan installatie-instructies voor Debian en Arch Linux. Voor dit artikel installeren we step-ca op Ubuntu Server 18.04 LTS en gaan we ervan uit dat je de certificaatautoriteit op Ubuntu Desktop 19.10 gebruikt.

Helaas zit step-ca nog niet in Debians repository’s en voor Ubuntu bestaat er nog geen ppa. Ga dus naar https://github.com/smallstep/certificates/releases en https://github.com/smallstep/cli/releases en download van elk het deb-bestand (alleen voor amd64) van de nieuwste versie. Installeer beide programma’s daarna. Op de server allebei:

server:~$ sudo dpkg -i Downloads/step-certificates_0.13.3_amd64.deb
server:~$ sudo dpkg -i Downloads/step-cli_0.13.3_amd64.deb

En op de client alleen step-cli:

client:~$ sudo dpkg -i Downloads/step-cli_0.13.3_amd64.deb

Even opletten, want de naamgeving is verwarrend: het pakket step-certificates installeert het programma step-ca en het pakket step-cli installeert het programma step (wat overigens een symbolische link is naar step-cli).

Configuratie

Initialiseer daarna de certificaatautoriteit op de server:

server:~$ step ca init

Je krijgt dan enkele vragen. Kies achtereenvolgens een naam voor je PKI (public key infrastructure), de hostname of het IP-adres van je ca (je kunt er meerdere gebruiken, afgescheiden door een komma), het adres waarop je ca luistert (ip:poort of hostname:poort), de naam van de standaard ‘provisioner’ (de partij die certificaten uitdeelt, je kunt hier je e-mailadres invullen), en een wachtwoord voor je ca. Als je dit laatste leeglaat, genereert step zelf een willekeurig wachtwoord. Nadien maakt step een rootcertificaat en bijbehorende geheime sleutel aan, een intermediate certificate en bijbehorende geheime sleutel en een configuratiebestand.

Met step-ca creëer je je eigen certificaatautoriteit in één opdracht.

Draai je certificaatautoriteit

Nu draai je de ca eenvoudig met de zojuist aangemaakte configuratie:

server:~$ step-ca $(step path)/config/ca.json

Je dient het ingestelde wachtwoord in te voeren, waarna de ca draait. Je kunt nu met de opdracht step nieuwe certificaten aan de ca aanvragen, certificaten intrekken, het rootcertificaat van de ca downloaden enzovoort.

Maar je wilt dat wellicht niet alleen op je server doen, maar ook op je desktop. Daar hadden we step-cli geïnstalleerd, we dienen dit nu alleen zo te configureren dat dit gebruikmaakt van step-ca dat op de server draait. Vraag daarvoor eerst op de server de vingerafdruk van het rootcertificaat op:

server:~$ step certificate fingerprint $(step path)/certs/root_ca.crt

Op je desktop bootstrap je nu de step-client:

client:~$ step ca bootstrap --fingerprint $FP --ca-url $CA

Hierin vervang je $FP door de vingerafdruk die de server toonde en $CA door de url van de ca, bijvoorbeeld https://pow.home:8443. Deze opdracht downloadt het rootcertificaat van je ca en maakt een standaardconfiguratie aan die naar de url en het rootcertificaat van je ca verwijst. Daarna kun je controleren of de communicatie met je ca correct verloopt:

client:~$ step ca health

Je zou de boodschap ok moeten zien. Als je verwacht dat je op deze client ook als rootgebruiker met je CA gaat communiceren, voer de bootstrap-opdracht dan ook met sudo uit.

Je kunt nu met step ca help zien welke opdrachten je kunt uitvoeren om je ca te beheren, zoals manueel certificaten aanvragen en vernieuwen (zonder gebruik van het ACME-protocol). Dat gaan we in dit artikel niet beschrijven, want we focussen hier ons op het ACME-protocol, dat dat allemaal voor ons automatisch op de achtergrond doet. Wat je wel eerst nog dient te doen, is het rootcertificaat van je CA installeren bij de rootcertificaten van je systeem:

client:~$ sudo step certificate install --all .step/certs/root_ca.crt

Dat doe je op elke client, en op alle apparaten die moeten verbinden met servers met certificaten die door je CA uitgereikt zijn. Mogelijk dien je ook het rootcertificaat nog te importeren in je webbrowser op al die apparaten.

ACME inschakelen

Nu verwacht je misschien dat ACME inschakelen een complexe aangelegenheid is, maar nee, met step-ca zou het niet eenvoudiger kunnen. Je voegt gewoon een provisioner toe van het type ACME:

server:~$ step ca provisioner add acme --type ACME

En herstart daarna step-ca. Omdat wij de server voorlopig nog gewoon handmatig opgestart hebben, sluit je die dus af met Ctrl+C en start je ze terug op. Als je daarna je provisioners opvraagt (dat kan ook op de client), dan zie je dat de standaardprovisioner gezelschap heeft gekregen van een provisioner van het type ACME:

client:~$ step ca provisioner list

Tls-certificaten aanvragen en vernieuwen

Nu de ACME-server draait, is het een kwestie van in je client te configureren dat die je eigen server gebruikt in plaats van die van Let’s Encrypt. Op hun blog geeft Smallstep instructies voor diverse clients (https://smallstep.com/blog/private-acme-server/).

We tonen eerst hoe je certificaten aan je ACME-server vraagt via step-cli. Stel dat je desktop de hostname x1.home heeft, dan vraag je als volgt een certificaat daarvoor aan:

client:~$ sudo step ca certificate x1.home x1.crt x1.key --ca-url https://pow.home:8443 --root $(step path)/certs/root_ca.crt

Je dient deze opdracht met sudo uit te voeren omdat step de http challenge (http-01) van het ACME-protocol gebruikt. Het programma krijgt immers van de ACME-server de opdracht om een willekeurig getal op een willekeurige url van het domein te plaatsen. De ACME-server verifieert zo of je de controle over het domein hebt. Maar dat gebeurt op poort 80, en een normale gebruiker kan geen server op poort 80 draaien. Daarvoor dienen de rootrechten. Met de opties –ca-url en –root dien je de url van de ca en het rootcertificaat aan te duiden. Overigens dient de firewall op je client ook poort 80 toe te staan.

Met de pijltjestoetsen kies je nu je ACME-provisioner, en daarna voert step de aanvraag uit. Na enkele seconden krijg je het certificaat en de sleutel in de bestanden x1.crt respectievelijk x1.key. Deze kun je nu als tls-certificaat gebruiken in je favoriete software. Een certificaat vernieuwen is even eenvoudig:

client:~$ sudo step ca renew x1.crt x1.key --ca-url https://pow.home:8443

Een certificaat aan je ACME-server aanvragen gaat met één opdracht.

Automatische vernieuwing

Het leuke van het ACME-protocol is uiteraard dat het aanvragen, toekennen en vernieuwen van certificaten volledig op de achtergrond kan gebeuren. Op het blog van Smallstep vind je informatie over hoe je dit configureert in talloze programma’s, zoals Caddy, Nginx, Apache, Traefik en Kubernetes.

Op https://gist.github.com/mmalone/12f5422b2ec68e64e9d11eae0c6ca47d vind je een voorbeeldwebserver in Python (helaas nog in Python 2…) die automatisch een certificaat verkrijgt en vernieuwt voordat het niet meer geldig is. Download het en installeer dan eerst enkele dependency’s:

client:~$ sudo pip install acme pem

Open dan het Python-script https.py en pas de volgende variabelen aan (de CA is hier pow.home op poort 8443 en de webserver x1.home op poort 10443):

# This is the ACME Directory URL for `step-ca`
DIRECTORY_URL = 'https://pow.home:8443/acme/acme/directory'

# This is the root certificate for `step-ca`
ROOT_CERTIFICATE = "/root/.step/certs/root_ca.crt"

# Email address used for creating ACME acount
ACC_EMAIL = "you@example.com"

# Domain name for the certificate.
DOMAIN = 'x1.home'

# Port to listen on for `http-01` challenge
ACME_PORT = 80

# Port our HTTPS server will listen on
HTTPS_PORT = 10443

Start daarna de webserver met:

client:~$ sudo python https.py

Als alles goed gaat, krijg je nu in de uitvoer het certificaat te zien dat je webserver van je CA verkrijgt. Je ziet ook dat de webserver elke 15 seconden controleert of het certificaat al vernieuwd dient te worden.

De echte test is natuurlijk de website bezoeken. Bezoek je in je webbrowser de webserver met als url https://x1.home:10443, dan zou je de boodschap “Hello, TLS!” moeten zien. Klik je op het slotje links in de adresbalk, dan krijg je te zien dat de verbinding beveiligd is. Je kunt het certificaat onderzoeken om te verifiëren of het door je CA ondertekend is. En als je deze testwebserver lang genoeg laat draaien, zul je zien dat het certificaat automatisch vernieuwd wordt.

Als je het rootcertificaat van je CA als vertrouwd hebt aangeduid, wordt je webserver ook in je webbrowser vertrouwd.