Skip to content

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

  1. Die Komponente läuft in der .pre-Stage
  2. Ein temporäres RSA-4096-Schlüsselpaar wird generiert
  3. Authentifizierung bei Vault über GitLabs JWT-Token
  4. Der öffentliche Schlüssel wird von Vaults SSH Secrets Engine signiert
  5. Privater Schlüssel (id_rsa) und signiertes Zertifikat (signed-key.pub) werden als Artifacts bereitgestellt
  6. 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 TrustedUserCAKeys in /etc/ssh/sshd_config hinterlegt
  • SSH-Dienst konfiguriert, signierte Zertifikate zu akzeptieren

Details zur Server-Konfiguration: Vault SSH Deployment

Einrichtung

Schritt 1: Component einbinden

yaml
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

yaml
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

InputBeschreibungPflichtStandard
ssh_roleVault SSH-Rolle für die Signierung des Public KeysNeingitlab-ci
valid_principalsGültige Principals für das signierte SSH-Zertifikat (kommasepariert)Nein(leer)
ssh_mount_pathMount-Pfad der Vault SSH Secrets EngineNeinssh_gitlab

Technische Details

EigenschaftWert
Stage.pre (läuft vor allen definierten Stages)
Runnerbuild-docker01
Imagehashicorp/vault:1.21
Vault URLhttps://vault.iteas.cloud
Auth-Pfadauth/jwt_gitlab/login
SSH-Key-TypRSA 4096-bit
Artifactsid_rsa (privater Schlüssel), signed-key.pub (signiertes Zertifikat)
Artifact-Ablauf1 Stunde

Exportierte Artifacts

DateiBeschreibung
id_rsaTemporärer privater SSH-Schlüssel
signed-key.pubVon 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:

bash
vault secrets enable -path=ssh_gitlab ssh
vault write ssh_gitlab/config/ca generate_signing_key=true

2. SSH-Rolle für GitLab CI:

bash
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:

hcl
path "ssh_gitlab/sign/gitlab-ci" {
  capabilities = ["create", "update"]
}

Vollständiges Beispiel mit Rsync-Deployment

yaml
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:
    - tags

Kombination mit vault-secrets

Beide Vault-Komponenten lassen sich kombinieren, z.B. um Secrets und SSH-Keys in derselben Pipeline zu nutzen:

yaml
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/

Iteas Tools Integration Platform Version v1.0.21

Version: v1.0.21 Version: v1.0.21
Commit: 7a0e1c11
Deployed at: 2026-09-24T13:56:52Z