Wie richte ich den SSH-Schlüsselsignaturprozess jedes Mal ein, wenn eine Ansible-Phase ausgeführt wird? Oder zumindest in bestimmten Abständen.
Ich habe eine Pipeline, die VMs mit Terraform erstellt und dann Ansible ausführt. In der Cloud-Init-Phase werden Host-Schlüssel erstellt und signiert, und auch öffentliche Benutzer-CA-Schlüssel werden konfiguriert. Client-/Host-CA-Behörden werden im HashiCorp Vault konfiguriert/ausgeführt. An diesem Punkt kann ich mich also, egal welche VMs bereitgestellt werden, per SSH mit jeder von ihnen verbinden, da ich den öffentlichen CA-Schlüssel des Hosts @cert-authority *.example.com ecdsa-sha2-nistp521 AAAAB3NzaC1yc2EAAA...
global festgelegt habe /etc/ssh/ssh_known_hosts
. Ich muss nur einen neuen persönlichen Schlüssel erstellen und ihn signieren, da meine TTL ziemlich kurz ist.
Aber das funktioniert in Jenkins nicht. Jenkins speichert alle SSH-Schlüssel unter /var/lib/jenkins/.ssh
und standardmäßig ist dort nichts. Wenn ich nur zu Testzwecken meine persönlichen Benutzerschlüssel (oder generierten Schlüssel) und Zertifikate + SSH-Konfigurationsdatei in kopiere /var/lib/jenkins/.ssh
, kann Jenkins Ansible problemlos ausführen. Aber ich kann die Jenkins-Schlüssel nicht jedes Mal generieren, signieren und kopieren, wenn ich in meinem Infra-Repo ein Commit durchführe. Das Erstellen langlebiger Zertifikate ist auch kein gutes Zeichen.
Wie sieht der idiomatische automatisierte Workflow für die Signierung und Rotation von SSH-Schlüsseln aus?
Antwort1
Ich werde die „SCHLECHTE“ Lösung selbst auflisten. Schlecht, weil die Schlüsselrotation dort manuell erfolgt und die TTL höchstwahrscheinlich zu lang sein wird, weil wir faul sind.
Im Vault müssen Sie eine neue "jenkins" SSH-Rolle mit der TTL wie folgt erstellen:52w
Dann müssen Sie idealerweise auf dem Jenkins-Host selbst neue Schlüssel erstellen.
ssh-keygen -t ecdsa -b 521 -f /var/lib/jenkins/.ssh/id_ecdsa -C "jenkins@jenkins-01"
Dann sing es bei Vault
vault write -field=signed_key ssh-client-signer/sign/jenkinsrole public_key=/var/lib/jenkins/.ssh/id_ecdsa.pub > /var/lib/jenkins/.ssh/id_ecdsa-cert.pub
Das bedeutet, dass Vault auf dem System sein sollte. ... es ist ein Dilemma – möchten Sie SSH-Schlüssel (einschließlich privater) über das Netzwerk kopieren, was ein bisschen nervt, oder möchten Sie Vault auf der Jenkins-Maschine installieren. Das bleibt Ihnen überlassen.
Nachdem Sie id_ecdsa-cert.pub
das Zertifikat haben, können Sie es überprüfen ssh-keygen -Lf /var/lib/jenkins/.ssh/id_ecdsa-cert.pub
und prüfen, ob die Gültigkeitsdauer, die Einzelheiten usw. richtig sind.
Da es höchstwahrscheinlich zu Abweichungen in der Infrastruktur kommt, /var/lib/jenkins/.ssh/config
wäre das statische Speichern der SSH-Konfiguration mühsam.
Stattdessen können Sie ansible-ssh.cfg
eine Datei mit folgendem Inhalt erstellen:
Host bastion
HostName bastion.example.com
IdentitiesOnly yes
IdentityFile ~/.ssh/id_ecdsa
CertificateFile ~/.ssh/id_ecdsa-cert.pub
Port 22
Protocol 2
User ansible
LogLevel INFO
Diese Datei kann (sollte) zusammen mit dem restlichen Ansible-Code platziert werden.
Dann in der ansible.cfg
Datei include SSH stanza
[ssh_connection]
ssh_args = -F ./ansible-ssh.cfg
Auf diese Weise greift Ansible immer auf aktuelle SSH-Konfigurationen zu.
Wenn Sie Terraform verwenden, ist es möglich, die SSH-Konfigurationsdatei dynamisch zu aktualisieren, um neue Hosts usw. einzuschließen.
Diese Lösung ist nicht nur an den Vault gebunden. Sie lässt sich ganz einfach mit dem selbst durchführen ssh-keygen
.
UPDATE: Schließlich landete ich bei einem kleinen Shell-Skript, das die Autorisierung mithilfe von Approle durchführt und dann das Zertifikat signiert. Der Systemd-Dienst und die Timer-Einheit führen das Shell-Skript aus, das die Zertifikatsrotation jeden Tag durchführt. An diesem Punkt verwendet Jenkins also seine eigenen neuen Benutzerzertifikate, um Terraform und Ansible auszuführen. https://stackoverflow.com/a/65875997/6651080