Vault SSH – SSH-Keys über Vault signieren
Die vault-ssh-Komponente generiert temporäre SSH-Schlüsselpaare und lässt diese von Vault signieren. Damit können sichere, kurzlebige SSH-Verbindungen für Deployments aufgebaut werden – ohne statische SSH-Keys in GitLab speichern zu müssen.
Hintergrund
Details zur Server-seitigen Konfiguration und manuellen Einrichtung finden sich unter GitLab SSH/Rsync Deployment mit Vault.
Funktionsweise
- Die Komponente läuft in der
.pre-Stage - Ein temporäres RSA-4096-Schlüsselpaar wird generiert
- Authentifizierung bei Vault über GitLabs JWT-Token
- Der öffentliche Schlüssel wird von Vaults SSH Secrets Engine signiert
- Privater Schlüssel (
id_rsa) und signiertes Zertifikat (signed-key.pub) werden als Artifacts bereitgestellt - Nachfolgende Jobs nutzen diese für SSH-/Rsync-Verbindungen
Voraussetzungen
Vault
- SSH Secrets Engine aktiviert und konfiguriert
- JWT-Authentifizierung für GitLab (siehe Vault GitLab JWT)
- SSH-Rolle für GitLab CI erstellt
Ziel-Server
- Vault CA Public Key als
TrustedUserCAKeysin/etc/ssh/sshd_confighinterlegt - SSH-Dienst konfiguriert, signierte Zertifikate zu akzeptieren
Details zur Server-Konfiguration: Vault SSH Deployment
Einrichtung
Schritt 1: Component einbinden
stages:
- build
- deploy
include:
- component: git.styrion.net/iteas/gitlab-components/vault-ssh@main
inputs:
valid_principals: "deploy_user"Schritt 2: SSH-Keys im Deploy-Job verwenden
deploy:
stage: deploy
image: alpine:latest
needs:
- job: vault-ssh
artifacts: true
before_script:
- apk add --no-cache openssh-client rsync
- eval $(ssh-agent -s)
- ssh-add ./id_rsa
script:
- rsync -avz -e "ssh -o StrictHostKeyChecking=no -i ./signed-key.pub -i ./id_rsa"
./build/ deploy_user@server.example.com:/var/www/app/
- ssh -o StrictHostKeyChecking=no -i ./signed-key.pub -i ./id_rsa
deploy_user@server.example.com "cd /var/www/app && php yii migrate --interactive=0"Konfigurationsoptionen
| Input | Beschreibung | Pflicht | Standard |
|---|---|---|---|
ssh_role | Vault SSH-Rolle für die Signierung des Public Keys | Nein | gitlab-ci |
valid_principals | Gültige Principals für das signierte SSH-Zertifikat (kommasepariert) | Nein | (leer) |
ssh_mount_path | Mount-Pfad der Vault SSH Secrets Engine | Nein | ssh_gitlab |
Technische Details
| Eigenschaft | Wert |
|---|---|
| Stage | .pre (läuft vor allen definierten Stages) |
| Runner | build-docker01 |
| Image | hashicorp/vault:1.21 |
| Vault URL | https://vault.iteas.cloud |
| Auth-Pfad | auth/jwt_gitlab/login |
| SSH-Key-Typ | RSA 4096-bit |
| Artifacts | id_rsa (privater Schlüssel), signed-key.pub (signiertes Zertifikat) |
| Artifact-Ablauf | 1 Stunde |
Exportierte Artifacts
| Datei | Beschreibung |
|---|---|
id_rsa | Temporärer privater SSH-Schlüssel |
signed-key.pub | Von Vault signiertes SSH-Zertifikat |
Sicherheitshinweis
Die Artifacts laufen nach 1 Stunde ab. Alle Deploy-Jobs müssen innerhalb dieses Zeitfensters abgeschlossen sein.
Pipeline-Regeln
Die Komponente läuft auf:
- Branch-Pipelines (außer wenn ein Merge Request offen ist)
- Tag-Pipelines
- Merge-Request-Pipelines (die auf den Default-Branch zielen)
Vault-Konfiguration
Für die Nutzung muss in Vault konfiguriert sein:
1. SSH Secrets Engine:
vault secrets enable -path=ssh_gitlab ssh
vault write ssh_gitlab/config/ca generate_signing_key=true2. SSH-Rolle für GitLab CI:
vault write ssh_gitlab/roles/gitlab-ci \
key_type=ca \
ttl=1h \
max_ttl=2h \
allow_user_certificates=true \
allowed_users="*" \
default_extensions="permit-pty="3. Policy für SSH-Zugriff:
path "ssh_gitlab/sign/gitlab-ci" {
capabilities = ["create", "update"]
}Vollständiges Beispiel mit Rsync-Deployment
stages:
- build
- deploy
include:
- component: git.styrion.net/iteas/gitlab-components/vault-ssh@main
inputs:
ssh_role: "gitlab-ci"
valid_principals: "f01_iteastools"
ssh_mount_path: "ssh_gitlab"
build:
stage: build
tags:
- build-ubuntu-2204-64
script:
- composer install --no-dev
artifacts:
paths:
- ./
deploy:
stage: deploy
image: alpine:latest
tags:
- build-docker01
needs:
- job: vault-ssh
artifacts: true
- job: build
artifacts: true
before_script:
- apk add --no-cache openssh-client rsync
- eval $(ssh-agent -s)
- ssh-add ./id_rsa
script:
- rsync -avz --delete
--exclude 'config/secrets.php'
--exclude 'runtime/*'
--exclude 'web/uploads/*'
-e "ssh -o StrictHostKeyChecking=no -i ./signed-key.pub -i ./id_rsa"
./src/ f01_iteastools@web04.styrion.net:/var/www/app/htdocs
- ssh -o StrictHostKeyChecking=no -i ./signed-key.pub -i ./id_rsa
f01_iteastools@web04.styrion.net
"cd /var/www/app/htdocs && composer install --no-dev && php yii migrate --interactive=0 && php yii cache/flush-all"
only:
- tagsKombination mit vault-secrets
Beide Vault-Komponenten lassen sich kombinieren, z.B. um Secrets und SSH-Keys in derselben Pipeline zu nutzen:
stages:
- build
- deploy
include:
- component: git.styrion.net/iteas/gitlab-components/vault-secrets@main
inputs:
secrets: |
COMPOSER_AUTH=secret/data/myapp/gitlab@composer_auth
- component: git.styrion.net/iteas/gitlab-components/vault-ssh@main
inputs:
valid_principals: "f01_iteastools"
build:
stage: build
needs:
- job: vault-secrets
artifacts: true
script:
- composer install --no-dev
deploy:
stage: deploy
needs:
- job: vault-ssh
artifacts: true
- job: build
before_script:
- eval $(ssh-agent -s)
- ssh-add ./id_rsa
script:
- rsync -avz -e "ssh -o StrictHostKeyChecking=no -i ./signed-key.pub -i ./id_rsa"
./src/ user@server:/var/www/app/