Vault SSH secrets engine configuration¶
Runbook for configuring Vault’s SSH secrets engine to issue short-lived SSH certificates. Teleport handles most infrastructure access, but some automated processes (deployment scripts, cron jobs, application-to-application connections) need SSH credentials without a human in the loop. Vault’s SSH secrets engine issues certificates valid for one hour. After that, they are gone. MaintenancePass123 is not mentioned here because it does not exist anymore.
Overview¶
The Vault SSH secrets engine operates as a certificate authority. It holds a signing key and issues signed SSH certificates to callers that present valid Vault credentials. The signed certificate grants SSH access to servers that trust the CA. No password is involved at any step.
Two modes are available: signed certificates (used here) and one-time passwords (not used; certificates are cleaner). Signed certificates work with standard OpenSSH; no special client is required beyond presenting the certificate alongside the corresponding private key.
Enabling the secrets engine¶
On the Vault cluster, authenticate as an admin and enable the engine:
export VAULT_ADDR="https://vault.golemtrust.am:8200"
vault login -method=userpass username=carrot.ironfoundersson
vault secrets enable -path=ssh ssh
Configuring the CA¶
Generate the CA signing key. Vault stores the private key internally; only the public key is exported:
vault write ssh/config/ca generate_signing_key=true
Export the public key for distribution to servers:
vault read -field=public_key ssh/config/ca > /tmp/vault-ssh-ca.pub
Distributing the CA public key¶
Every server that should accept Vault-signed certificates must trust the CA. Copy the public key to each server and configure OpenSSH to trust it:
cp /tmp/vault-ssh-ca.pub /etc/ssh/vault-ssh-ca.pub
chmod 644 /etc/ssh/vault-ssh-ca.pub
Add to /etc/ssh/sshd_config:
TrustedUserCAKeys /etc/ssh/vault-ssh-ca.pub
Reload SSH:
systemctl reload sshd
Repeat on every server that should accept Vault-issued certificates.
Creating roles¶
Define roles for each use case. A role specifies which Linux users the certificate may be used to log in as, the certificate TTL, and any key type requirements.
Role for deployment scripts (restricted to the deploy Linux user, short TTL):
vault write ssh/roles/deploy \
key_type=ca \
allowed_users=deploy \
default_user=deploy \
ttl=1h \
max_ttl=4h \
allow_user_certificates=true
Role for golem operators (Mr. Pump and his team; restricted to the golem-operator Linux user):
vault write ssh/roles/golem-operator \
key_type=ca \
allowed_users=golem-operator \
default_user=golem-operator \
ttl=1h \
max_ttl=1h \
allow_user_certificates=true
Role for emergency admin access (restricted to root, MFA required at the Vault level via an MFA method bound to this role, TTL 1 hour, not renewable):
vault write ssh/roles/emergency-admin \
key_type=ca \
allowed_users=root \
default_user=root \
ttl=1h \
max_ttl=1h \
allow_user_certificates=true
Vault policies for certificate issuance¶
Create policies that permit callers to sign certificates using specific roles:
vault policy write ssh-deploy - << 'EOF'
path "ssh/sign/deploy" {
capabilities = ["create", "update"]
}
EOF
vault policy write ssh-golem-operator - << 'EOF'
path "ssh/sign/golem-operator" {
capabilities = ["create", "update"]
}
EOF
Assign the ssh-deploy policy to the deploy-agent AppRole. Assign ssh-golem-operator to the golem authentication token (see the golem authentication runbook for how golem identities are managed in Keycloak; Vault authentication for golems uses a separate AppRole).
Requesting a certificate¶
A script or application requests a certificate by generating an SSH key pair locally, submitting the public key to Vault, and receiving a signed certificate back:
ssh-keygen -t ed25519 -f /tmp/deploy-key -N ""
vault write ssh/sign/deploy \
public_key=@/tmp/deploy-key.pub \
valid_principals=deploy
The response contains a signed_key field. Write it to a file:
vault write -field=signed_key ssh/sign/deploy \
public_key=@/tmp/deploy-key.pub \
valid_principals=deploy > /tmp/deploy-key-cert.pub
Connect using the key and certificate:
ssh -i /tmp/deploy-key -i /tmp/deploy-key-cert.pub deploy@auth.golemtrust.am
The private key and certificate are temporary; delete them after use:
rm /tmp/deploy-key /tmp/deploy-key.pub /tmp/deploy-key-cert.pub
Automated scripts should generate a fresh key pair on each invocation, request a certificate, connect, complete their work, and clean up. The one-hour TTL is the outer bound; a well-written script holds the certificate for seconds, not minutes.
Verification¶
Generate a test certificate using the deploy role and attempt to connect to a server:
ssh-keygen -t ed25519 -f /tmp/test-key -N "" -q
vault write -field=signed_key ssh/sign/deploy \
public_key=@/tmp/test-key.pub > /tmp/test-key-cert.pub
ssh-keygen -L -f /tmp/test-key-cert.pub
The ssh-keygen -L output shows the certificate’s principals, valid-after, valid-before, and CA fingerprint. Confirm that the principals match the role’s allowed_users and that the validity window is correct.
Attempt an SSH connection. It should succeed without a password prompt and be rejected after the certificate expires.
Audit¶
Every certificate issuance is recorded in the Vault audit log. To see recent SSH certificate requests:
grep "ssh/sign" /opt/vault/logs/audit.log | tail -20
Each entry includes the Vault token that made the request, the role used, and the timestamp. This provides a complete record of who requested which certificate and when, even if the certificate itself has long since expired.