A hashicorp vault mfa ssh session ttl design can satisfy MA.L2-3.7.5 by requiring MFA before Vault issues a short-lived SSH certificate, limiting the certificate to a maintenance account, and using a server-side session timer to close the SSH shell even if the technician forgets to disconnect. Vault controls identity verification, certificate issuance, and credential lifetime; the SSH server enforces the maximum live-session duration, while the ISSO or FSO retains responsibility for approving maintenance, reviewing evidence, and confirming the external connection is closed when work is complete.
What does hashicorp vault mfa ssh session ttl automation handle, and what remains manual?
NIST SP 800-171 Rev. 2 practice MA.L2-3.7.5 requires two distinct outcomes: MFA must be used to establish nonlocal maintenance sessions over external networks, and those sessions must be terminated when the maintenance activity is complete. A Vault-issued SSH certificate with a 20-minute maximum lifetime is useful, but certificate expiration alone does not reliably terminate an SSH session already in progress. The implementation needs both a short certificate TTL and a server-side timeout.
| Activity | Automated control | ISSO/FSO responsibility |
|---|---|---|
| Authenticate remote technician | Vault MFA enforcement and an IdP MFA claim before the SSH signing policy is available | Approve authorized maintenance personnel and remove access when duties change |
| Issue maintenance access | Vault SSH secrets engine signs an ephemeral public key for one approved principal | Confirm the requested system, maintenance window, and ticket are authorized |
| Limit credential reuse | SSH certificate expires after 20 minutes; Vault token is also short-lived | Set a duration appropriate to the maintenance workflow and document exceptions |
| End the live connection | ForceCommand runs the maintenance shell through timeout; SSH also closes idle or dead clients |
Require technicians to exit when work is complete and confirm ticket closure |
| Preserve evidence | Vault audit devices, SSH authentication logs, and SIEM correlation rules | Review alerts, retain records, and investigate abnormal activity |
For a small contractor, keep the boundary clear: a CI runner or service account must never receive the human remote-maintenance signing policy. A scheduled job can validate configuration drift, but it cannot perform MFA on behalf of a technician.
How can you automate MFA-gated SSH certificate issuance?
The following Bash workflow assumes Vault Enterprise MFA enforcement, an existing OIDC authentication mount, and an identity provider configured to require MFA for the remote-maintenance group. Vault MFA enforcement adds a second factor at the Vault login layer; the OIDC role should also require an MFA-related claim, such as an amr value containing mfa, where the identity provider supports that claim.
The first script creates a Duo MFA method, applies MFA enforcement to the OIDC mount, enables an SSH certificate authority, and creates a narrowly scoped signing role. Store the Duo integration values in an approved secret store or protected deployment environment; do not place them in a repository or a Terraform variable file.
#!/usr/bin/env bash
set -euo pipefail
: "${VAULT_ADDR:?Set VAULT_ADDR}"
: "${VAULT_TOKEN:?Use an approved Vault administrator token}"
: "${DUO_IKEY:?Load from protected automation secrets}"
: "${DUO_SKEY:?Load from protected automation secrets}"
: "${DUO_HOST:?Example: api-xxxxxxxx.duosecurity.com}"
export VAULT_ADDR VAULT_TOKEN
OIDC_ACCESSOR="$(vault auth list -format=json | jq -r '.["oidc/"].accessor')"
MFA_ID="$(vault write -format=json sys/mfa/method/duo \
name=remote-maint-duo \
integration_key="$DUO_IKEY" \
secret_key="$DUO_SKEY" \
api_hostname="$DUO_HOST" | jq -r '.data.method_id')"
vault write identity/mfa/login-enforcement/remote-maintenance \
mfa_method_ids="$MFA_ID" \
auth_method_accessors="$OIDC_ACCESSOR"
vault secrets list -format=json | jq -e 'has("ssh-client-signer/")' \
|| vault secrets enable -path=ssh-client-signer ssh
vault write ssh-client-signer/config/ca generate_signing_key=true
vault write ssh-client-signer/roles/remote-maint \
key_type=ca \
allow_user_certificates=true \
allowed_users=maint-remote \
default_user=maint-remote \
ttl=20m \
max_ttl=20m \
allowed_extensions=permit-pty \
default_extensions='{"permit-pty":""}'
cat > remote-maint-policy.hcl <<'EOF'
path "ssh-client-signer/sign/remote-maint" {
capabilities = ["create", "update"]
}
EOF
vault policy write remote-maint remote-maint-policy.hcl
Attach the remote-maint policy only to the OIDC role or identity group used for approved maintenance staff. Do not grant that group access to arbitrary Vault paths, SSH host keys, or broader privileged-administration policies. The policy is intentionally limited to signing a certificate through one role.
How should the SSH server enforce the live-session limit?
On every in-scope maintenance target, install the Vault SSH CA public key and restrict the maintenance account. This example fits a 62-person electronics and PCB manufacturer where two outside field-service technicians maintain a Linux test-data server and a production programming appliance during approved evening windows. The company’s normal engineering accounts cannot use this maintenance account.
#!/usr/bin/env bash
set -euo pipefail
vault read -field=public_key ssh-client-signer/public_key \
| sudo tee /etc/ssh/trusted-user-ca-keys.pem > /dev/null
sudo install -m 0755 /dev/stdin /usr/local/sbin/maintenance-shell <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
limit_seconds="${1:?Missing session limit}"
logger -p authpriv.notice "remote maintenance shell started for ${USER}"
exec /usr/bin/timeout --foreground --signal=TERM --kill-after=30s \
"$limit_seconds" /bin/bash -l
EOF
sudo tee /etc/ssh/sshd_config.d/50-remote-maintenance.conf > /dev/null <<'EOF'
TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem
ClientAliveInterval 60
ClientAliveCountMax 2
Match User maint-remote
PasswordAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
PermitRootLogin no
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
ForceCommand /usr/local/sbin/maintenance-shell 1200
EOF
sudo sshd -t
sudo systemctl reload sshd
The 1,200-second forced shell matches the 20-minute certificate maximum. The certificate prevents new access after expiration; the forced command closes an established interactive shell at the same limit. If the technician completes work earlier, they must use exit, which is the operational termination event recorded in the maintenance ticket. Use a separate, purpose-built transfer method for files because a forced interactive shell will interfere with SCP and similar workflows.
What does the technician’s approved workflow look like?
#!/usr/bin/env bash
set -euo pipefail
KEY="$(mktemp -u "${TMPDIR:-/tmp}/maint-key.XXXXXX")"
CERT="${KEY}-cert.pub"
trap 'rm -f "$KEY" "$KEY.pub" "$CERT"' EXIT
ssh-keygen -q -t ed25519 -N "" -f "$KEY"
# Browser-based OIDC login must complete the approved MFA challenge.
vault login -method=oidc role=remote-maint
vault write -field=signed_key \
ssh-client-signer/sign/remote-maint \
public_key=@"$KEY.pub" \
valid_principals=maint-remote \
ttl=20m > "$CERT"
ssh -i "$KEY" \
-o CertificateFile="$CERT" \
-o IdentitiesOnly=yes \
maint-remote@maintenance-gateway.example.mil
# Technician exits when maintenance is complete; the trap removes local keys.
How should this be integrated into CI/CD or scheduled jobs?
Use scheduled automation for configuration validation, not for human session creation. A GitHub Actions workflow running from a protected, self-hosted runner can authenticate to Vault using a dedicated GitHub JWT role with read-only access to the SSH role configuration. It should verify that the certificate ceiling remains 20 minutes and that each target still has the required SSH server directives.
name: Validate remote-maintenance controls
on:
schedule:
- cron: "17 3 * * 1-5"
workflow_dispatch:
permissions:
id-token: write
contents: read
jobs:
validate:
runs-on: [self-hosted, management-subnet]
steps:
- uses: actions/checkout@v4
- name: Authenticate with Vault using GitHub OIDC
uses: hashicorp/vault-action@v3
with:
url: $
method: jwt
path: jwt
role: github-compliance-read
- name: Check certificate and SSH session limits
run: |
set -euo pipefail
vault read -format=json ssh-client-signer/roles/remote-maint \
| jq -e '.data.max_ttl == 1200 and .data.ttl == 1200'
ssh maintenance-gateway.example.mil \
'sudo sshd -T -C user=maint-remote,host=maintenance-gateway,addr=10.20.30.40' \
| grep -Fx 'forcecommand /usr/local/sbin/maintenance-shell 1200'
Route a failed workflow to the compliance ticket queue. A failed validation does not prove an unauthorized session occurred, but it does establish that a control dependency needs immediate review before the next external maintenance window.
Which monitoring and alerting hooks provide MA.L2-3.7.5 evidence?
| Event source | Alert or evidence rule | Why it matters |
|---|---|---|
| Vault audit log | Alert when ssh-client-signer/sign/remote-maint is used outside approved windows or by an unrecognized identity |
Shows the MFA-gated certificate request and the identity that initiated it |
| Vault audit log | Alert on changes to identity/mfa/login-enforcement, SSH roles, or policies |
Detects bypass attempts and control drift |
| Linux auth and journal logs | Correlate certificate login, forced-shell start, logout, and timeout events by account and source IP | Supports evidence that the nonlocal session ended |
| Firewall or VPN logs | Alert if the technician source remains connected after the approved window | Confirms the external network path is closed, not merely the SSH process |
Forward Vault audit logs to the SIEM through an approved audit device, protect them from alteration, and retain the ticket number, technician identity, target system, certificate issuance event, SSH login event, and logout or timeout event as one reviewable record.
What failure modes should the ISSO plan for?
| Failure mode | Safe behavior | Required response |
|---|---|---|
| Duo or the identity provider is unavailable | Vault does not issue a maintenance certificate | Delay maintenance or use the formally approved emergency-access process with documented authorization |
| Vault is unavailable after a certificate is issued | Existing certificate works only until its 20-minute expiration; no new certificate can be issued | Do not extend the session informally; restore Vault and review the outage record |
| Technician loses network connectivity | ClientAliveInterval and ClientAliveCountMax clear abandoned sessions |
Verify the server logged disconnect and the VPN or firewall path ended |
| Forced-command configuration is removed | Scheduled validation fails and should create a high-priority ticket | Restore configuration, determine the change source, and assess sessions during exposure |
| Certificate or local key is copied | Copied material becomes unusable after the certificate TTL, assuming the private key is removed locally | Revoke affected identity access, investigate, and rotate the SSH CA if compromise is suspected |
As the ISSO or FSO, schedule a tabletop test with the maintenance owner this month: prove MFA is challenged, prove the forced shell ends at the configured limit, and attach the resulting Vault, SSH, and firewall evidence to your MA.L2-3.7.5 assessment record.