
Der letzte Blogpost Interne Certificate Authority mit Step-Ca behandelte den Aufbau einer Zertifikatsverwaltung mittels Step-CA. Nachdem die Step-CA nun erfolgreich aufgesetzt wurde und wir mit dieser Zertifikate ausstellen können, können wir auch gleich ein weiteres Problem angehen: Die Authentifizierung von Usern und Hosts im Kontext von SSH-Verbindungen.
Obwohl eine Step-CA hierfür nicht zwingend erforderlich ist, da eine zertifikatsbasierte Authentifizierung für SSH auch problemlos mit den Standardwerkzeugen von OpenSSH umgesetzt werden kann, vereinfacht die Step-CA die Verwaltung und Einrichtung in einigen Punkten.
Das folgende docker-compose Setup baut auf der bestehenden Step-CA-Umgebung auf, erweitert das bestehende Setup jedoch um zwei zusätzliche Secrets und einen weiteren Initialisierungs-Container. Die Aufgabe dieses Containers besteht darin, sicherzustellen, dass die Step-CA (im Container) dieselben Host- und Benutzerzertifikate verwendet wie der Host selbst.
version: "3.7"
name: step-ca
volumes:
step-ca-data:
networks:
step-ca-net:
secrets:
init_secret:
file: ./init_secret.txt
ca_private_host_key: # privater Key des Hosts
file: /etc/ssh/ssh_host_ecdsa_key
ca_private_user_key:
file: /etc/ssh/ssh_user_ecdsa_key
services:
step-ca:
container_name: step-ca
image: smallstep/step-ca:0.27.2
volumes:
- step-ca-data:/home/step
command:
secrets:
- init_secret
environment:
DOCKER_STEPCA_INIT_PASSWORD_FILE: /run/secrets/init_secret
DOCKER_STEPCA_INIT_NAME: ca.example.com
DOCKER_STEPCA_INIT_DNS_NAMES: localhost,192.168.xxx.xxx,ca.example.com
DOCKER_STEPCA_INIT_REMOTE_MANAGEMENT: true
DOCKER_STEPCA_INIT_PROVISIONER_NAME: admin
DOCKER_STEPCA_INIT_SSH: true
DOCKER_STEPCA_INIT_ACME: true
ports:
- 9000:9000
networks:
- step-ca-net
step-ca-ssh-setup:
container_name: step-ca-ssh-setup
image: docker:latest
volumes:
- step-ca-data:/home/step
- /var/run/docker.sock:/var/run/docker.sock
- ./docker-compose.yaml:/docker-compose.yaml
secrets:
- ca_private_host_key
- ca_private_user_key
depends_on:
- step-ca
restart: no
entrypoint: ["sh", "-c", "sleep 1 \
&& cat /run/secrets/ca_private_host_key > /home/step/secrets/ssh_host_ca_key \
&& cat /run/secrets/ca_private_user_key > /home/step/secrets/ssh_user_ca_key \
&& docker compose restart step-ca" ]
Standardmäßig verwendet Step-CA für die Signatur den internen privaten Host-Schlüssel des Containers.
Um sicherzustellen, dass die Signatur mit Step durchgeführt wird und die anschließende Zertifikatsvalidierung gegen den Host erfolgreich ist, nutzen wir den Host-Schlüssel für die Signierung:
step ssh certificate --host --sign foo.example.com /etc/ssh/ssh_host_ecdsa_key.pub
Dabei wird das signierte Zertifikat unter
/etc/ssh/ssh_host_ecdsa_key-cert.pub
auf dem Host gespeichert.
Zusätzlich müssen wir SSHD so konfigurieren, dass das signierte Host-Zertifikat vom Host zur Verifizierung herangezogen wird:
In /etc/ssh/sshd_config
ergänzen:
HostCertificate /etc/ssh/step-ca/ssh_host_ca_key-cert.pub
Restart von SSHD:
systemctl restart sshd
Nun können wir dem Client mitteilen, dass er dem Host-Zertifikat vertrauen soll:
PUB_CERT=$(step ssh config --host --roots)
Für den Benutzer:
echo "@cert-authority * ${PUB_CERT}" >> ~/.ssh/known_hosts
Oder Systemweit:
echo "@cert-authority * ${PUB_CERT}" | sudo tee -a /etc/ssh/ssh_known_hosts
Anschließend ist es möglich, sich per SSH zu verbinden, wobei standardmäßig allen von der Host-CA ausgestellten Host-Zertifikaten vertraut wird. Dadurch entfallen die Warnmeldungen über unbekannte Hosts:
ssh test.foobar.com
Authentifikation über signierte User Zertifikate
Um die Authentifizierung mittels Benutzerzertifikaten zu ermöglichen, sind noch folgende Anpassungen erforderlich:
1. Den SSH-Daemon über die /etc/ssh/sshd_config so konfigurieren, dass Benutzerzertifikate gegen die Benutzer-CA validiert werden:
HostKey /etc/ssh/ssh_host_ecdsa_key
HostCertificate /etc/ssh/ssh_host_ecdsa_key-cert.pub
Restart von SSHD:
systemctl restart sshd
2. Ein SSH-Keypair erzeugen und mit der CA signieren:
step ssh certificate --ca-url https://foo.example.com:9000 john@foo.example.com id_ecdsa --principal john
Um existierende Keys neu zu signieren:
step ssh certificate --ca-url=https://foo.example.com:9000 john@foo.example.com id_ecdsa.pub --sign --private-key=id_ecdsa --principal john
3. Das generierte Zertifikat validieren:
ssh-keygen -Lf id_ecdsa-cert.pub
4. Optional: einen passenden Eintrag in der ~/.ssh/config anlegen:
Host foobar
HostName foo.example.com
User john
IdentityFile ~/.ssh/id_ecdsa
CertificateFile ~/.ssh/id_ecdsa-cert.pub