HashiCorp Vault — Production Exercises

3 minute read

Practice production operations with these exercises.


Exercise 1 — Raft Snapshot and Restore

Task: Backup and restore Vault data using Raft snapshots.

  1. Store some test secrets in KV
  2. Take a Raft snapshot
  3. Add more secrets
  4. Restore the snapshot
  5. Verify only the original secrets exist
Show Answer
# Store initial secrets
vault kv put secret/app1 key=original-value-1
vault kv put secret/app2 key=original-value-2

# Take a snapshot
vault operator raft snapshot save test-backup.snap
ls -lh test-backup.snap

# Add more secrets AFTER the snapshot
vault kv put secret/app3 key=post-snapshot-value

# Verify app3 exists
vault kv get secret/app3  # ✅ exists

# Restore the snapshot
vault operator raft snapshot restore -force test-backup.snap

# Verify: app1 and app2 should exist, app3 should not
vault kv get secret/app1  # ✅ exists
vault kv get secret/app2  # ✅ exists
vault kv get secret/app3  # ❌ gone (restored to pre-snapshot state)

Exercise 2 — Root Token Generation

Task: Practice the emergency root token generation workflow.

Show Answer
# In dev mode, you already have a root token
# In production, simulate the generation process:

# Initialize
INIT_OUTPUT=$(vault operator generate-root -init -format=json)
NONCE=$(echo "$INIT_OUTPUT" | jq -r '.nonce')
OTP=$(echo "$INIT_OUTPUT" | jq -r '.otp')

echo "Nonce: $NONCE"
echo "OTP: $OTP"

# Provide unseal key(s) — in dev mode there's only one
# vault operator generate-root -nonce=$NONCE
# Enter unseal key when prompted

# After threshold is met:
# ENCODED_TOKEN is returned
# vault operator generate-root -decode=$ENCODED_TOKEN -otp=$OTP
# Returns the root token

# IMPORTANT: Use it for the emergency task, then revoke it
# vault token revoke $ROOT_TOKEN

Key points:

  • Requires coordination among unseal key holders
  • The OTP is single-use
  • Always revoke the root token after emergency use

Exercise 3 — Hardening Audit

Task: Audit your dev Vault for hardening gaps and fix them.

  1. Check if audit logging is enabled
  2. Check which auth methods are enabled
  3. Disable any unnecessary auth methods
  4. Enable an audit device
  5. Verify audit logs are being written
Show Answer
# Check audit devices
vault audit list
# Likely empty in dev mode

# Check auth methods
vault auth list
# Look for anything unnecessary

# Enable file audit
vault audit enable file file_path=/tmp/vault-audit.log

# Verify it's enabled
vault audit list

# Perform an action (generates audit log)
vault kv put secret/test-audit key=value

# Check the audit log
cat /tmp/vault-audit.log | jq '.type'
# Should show "request" and "response" entries

# Disable unused auth methods (example)
# vault auth disable approle/

# Check seal status and config
vault status

Exercise 4 — Lease Management

Task: Create dynamic database credentials and practice lease management.

Show Answer
# Assuming database secrets engine is configured
# (See Chapter 6 for setup)

# Generate credentials
vault read database/creds/readonly
# Note the lease_id

# List active leases
vault list sys/leases/lookup/database/creds/readonly/

# Renew a lease
vault lease renew database/creds/readonly/<lease-id>

# Revoke a specific lease
vault lease revoke database/creds/readonly/<lease-id>

# Generate more credentials
vault read database/creds/readonly
vault read database/creds/readonly
vault read database/creds/readonly

# Revoke ALL leases under this path
vault lease revoke -prefix database/creds/readonly/

# Verify no active leases
vault list sys/leases/lookup/database/creds/readonly/

Exercise 5 — Operational Health Script

Task: Write a health check script that validates your Vault deployment.

Show Answer
#!/bin/bash
# vault-health-check.sh
set -euo pipefail

VAULT_ADDR="${VAULT_ADDR:-http://127.0.0.1:8200}"
ERRORS=0

echo "=== Vault Health Check ==="
echo "Target: $VAULT_ADDR"
echo ""

# 1. Check if Vault is reachable
echo -n "Vault reachable: "
if curl -s "$VAULT_ADDR/v1/sys/health" > /dev/null 2>&1; then
    echo "✅"
else
    echo "❌ Cannot reach Vault"
    ERRORS=$((ERRORS + 1))
fi

# 2. Check seal status
echo -n "Seal status: "
SEALED=$(vault status -format=json 2>/dev/null | jq -r '.sealed')
if [ "$SEALED" = "false" ]; then
    echo "✅ Unsealed"
else
    echo "❌ SEALED"
    ERRORS=$((ERRORS + 1))
fi

# 3. Check HA status
echo -n "HA mode: "
vault status -format=json 2>/dev/null | jq -r '.ha_enabled'

# 4. Check audit devices
echo -n "Audit devices: "
AUDIT_COUNT=$(vault audit list -format=json 2>/dev/null | jq 'length')
if [ "$AUDIT_COUNT" -gt 0 ]; then
    echo "✅ $AUDIT_COUNT enabled"
else
    echo "⚠️ No audit devices (recommended: at least 2)"
fi

# 5. Check Vault version
echo -n "Version: "
vault status -format=json 2>/dev/null | jq -r '.version'

echo ""
echo "=== Check Complete ($ERRORS errors) ==="
exit $ERRORS
chmod +x vault-health-check.sh
./vault-health-check.sh

What’s Next?

Production operations covered. Now let’s build complete projects that combine everything you’ve learned.

Next Chapter: Practice Projects