Available for day contractsFrom 21st September I have availability for day and half day contracts. Please contact for more information.

Contact →
mikepreston.org

HashiCorp Vault

A secrets management tool for securely storing, accessing, and managing sensitive data like tokens, passwords, certificates, and encryption keys.

HashiCorp Vault Cheatsheet

A secrets management tool for securely storing, accessing, and managing sensitive data like tokens, passwords, certificates, and encryption keys.


Overview

HashiCorp Vault provides a unified interface for managing secrets while providing tight access control and recording a detailed audit log. It handles leasing, key revocation, key rolling, and auditing, making it essential for modern infrastructure security.

Vault ArchitectureStorage BackendSecret EnginesConsulClient ApplicationsVault APIAuthenticationPoliciesKV StoreDatabasePKI CertificatesTransit EncryptionIntegrated RaftS3/Cloud StorageVault ArchitectureStorage BackendSecret EnginesConsulClient ApplicationsVault APIAuthenticationPoliciesKV StoreDatabasePKI CertificatesTransit EncryptionIntegrated RaftS3/Cloud Storage

Secret Engines

Key Concepts

  • Secret Engine: A component that stores, generates, or encrypts data
  • Mount Path: The location where a secret engine is enabled (e.g., secret/, database/)
  • Versioning: KV v2 supports versioned secrets with history
  • Lease: Time-bound access to secrets with automatic revocation

Common Commands

# List enabled secret engines
vault secrets list

# Enable a secret engine
vault secrets enable -path=secret kv-v2
vault secrets enable database
vault secrets enable pki

# Disable a secret engine
vault secrets disable secret/

# Tune secret engine settings
vault secrets tune -max-lease-ttl=87600h pki/

KV (Key-Value) Engine

# KV Version 2 (recommended)
vault secrets enable -version=2 -path=secret kv

# Write a secret
vault kv put secret/myapp/config username="admin" password="s3cr3t"

# Read a secret
vault kv get secret/myapp/config
vault kv get -field=password secret/myapp/config

# Read specific version
vault kv get -version=2 secret/myapp/config

# List secrets
vault kv list secret/myapp

# Delete secret (soft delete in v2)
vault kv delete secret/myapp/config

# Permanently destroy specific version
vault kv destroy -versions=1,2 secret/myapp/config

# Undelete a secret
vault kv undelete -versions=1 secret/myapp/config

# View metadata
vault kv metadata get secret/myapp/config

Database Secret Engine

# Enable database engine
vault secrets enable database

# Configure PostgreSQL connection
vault write database/config/my-postgresql-database \
    plugin_name=postgresql-database-plugin \
    allowed_roles="my-role" \
    connection_url="postgresql://{{username}}:{{password}}@localhost:5432/mydb" \
    username="vault-admin" \
    password="vault-password"

# Create a role for dynamic credentials
vault write database/roles/my-role \
    db_name=my-postgresql-database \
    creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \
        GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
    default_ttl="1h" \
    max_ttl="24h"

# Generate dynamic credentials
vault read database/creds/my-role

# Rotate root credentials
vault write -force database/rotate-root/my-postgresql-database

PKI Secret Engine

# Enable PKI engine
vault secrets enable pki

# Configure max lease TTL
vault secrets tune -max-lease-ttl=87600h pki/

# Generate root CA
vault write -field=certificate pki/root/generate/internal \
    common_name="example.com" \
    ttl=87600h > CA_cert.crt

# Configure CA and CRL URLs
vault write pki/config/urls \
    issuing_certificates="http://vault.example.com:8200/v1/pki/ca" \
    crl_distribution_points="http://vault.example.com:8200/v1/pki/crl"

# Create a role for issuing certificates
vault write pki/roles/example-dot-com \
    allowed_domains="example.com" \
    allow_subdomains=true \
    max_ttl="720h"

# Issue a certificate
vault write pki/issue/example-dot-com \
    common_name="app.example.com" \
    ttl="24h"

# Revoke a certificate
vault write pki/revoke serial_number="<serial>"

Authentication Methods

Key Concepts

  • Auth Method: A way to authenticate users or machines to Vault
  • Token: The core authentication mechanism; all auth methods produce tokens
  • Entity: A representation of a user or machine across auth methods
  • Alias: Maps an auth method identity to an entity
Authentication FlowCredentialsValidatesAuthorisesGrants AccessUser/ApplicationAuth MethodVault TokenAttached PoliciesAccess SecretsAuthentication FlowCredentialsValidatesAuthorisesGrants AccessUser/ApplicationAuth MethodVault TokenAttached PoliciesAccess Secrets

Token Authentication

# Login with token
vault login <token>

# Create a new token
vault token create

# Create token with specific policy
vault token create -policy="my-policy" -ttl=1h

# Create orphan token (no parent)
vault token create -orphan

# Create periodic token
vault token create -period=24h

# Lookup current token
vault token lookup

# Lookup specific token
vault token lookup -accessor <accessor>

# Renew token
vault token renew
vault token renew -increment=1h

# Revoke token
vault token revoke <token>
vault token revoke -accessor <accessor>

# Revoke a token but orphan its children (leave them valid)
vault token revoke -mode=orphan <token>

Kubernetes Authentication

# Enable Kubernetes auth
vault auth enable kubernetes

# Configure Kubernetes auth
vault write auth/kubernetes/config \
    kubernetes_host="https://kubernetes.default.svc:443" \
    kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
    token_reviewer_jwt=@/var/run/secrets/kubernetes.io/serviceaccount/token

# Create a role
vault write auth/kubernetes/role/myapp \
    bound_service_account_names=myapp-sa \
    bound_service_account_namespaces=default \
    policies=myapp-policy \
    ttl=1h

# Login from Kubernetes pod
vault write auth/kubernetes/login \
    role=myapp \
    jwt=@/var/run/secrets/kubernetes.io/serviceaccount/token

AppRole Authentication

# Enable AppRole auth
vault auth enable approle

# Create an AppRole
vault write auth/approle/role/my-app \
    secret_id_ttl=10m \
    token_num_uses=10 \
    token_ttl=20m \
    token_max_ttl=30m \
    secret_id_num_uses=40 \
    policies="my-policy"

# Get RoleID
vault read auth/approle/role/my-app/role-id

# Generate SecretID
vault write -f auth/approle/role/my-app/secret-id

# Login with AppRole
vault write auth/approle/login \
    role_id="<role-id>" \
    secret_id="<secret-id>"

# Destroy specific SecretID
vault write auth/approle/role/my-app/secret-id/destroy \
    secret_id="<secret-id>"

Other Auth Methods

# LDAP Authentication
vault auth enable ldap
vault write auth/ldap/config \
    url="ldaps://ldap.example.com" \
    userdn="ou=Users,dc=example,dc=com" \
    groupdn="ou=Groups,dc=example,dc=com" \
    groupfilter="(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))"

vault login -method=ldap username=mitchellh

# GitHub Authentication
vault auth enable github
vault write auth/github/config organization=myorg
vault write auth/github/map/teams/engineering value=eng-policy

vault login -method=github token="<github-token>"

# OIDC Authentication
vault auth enable oidc
vault write auth/oidc/config \
    oidc_discovery_url="https://accounts.google.com" \
    oidc_client_id="<client-id>" \
    oidc_client_secret="<client-secret>" \
    default_role="demo"

Policies and Access Control

Key Concepts

  • Policy: A named set of permissions written in HCL or JSON
  • Capabilities: The operations allowed (create, read, update, delete, list, sudo, deny)
  • Path: The secret path the policy applies to
  • Templating: Dynamic policy paths using identity information

Policy Syntax

# Example policy: my-policy.hcl

# Allow full access to app secrets
path "secret/data/myapp/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

# Read-only access to shared secrets
path "secret/data/shared/*" {
  capabilities = ["read", "list"]
}

# Deny access to admin secrets
path "secret/data/admin/*" {
  capabilities = ["deny"]
}

# Allow managing own tokens
path "auth/token/renew-self" {
  capabilities = ["update"]
}

path "auth/token/revoke-self" {
  capabilities = ["update"]
}

# Use templating for user-specific paths
path "secret/data/users/{{identity.entity.name}}/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

# Require specific parameters
path "secret/data/restricted" {
  capabilities = ["create", "update"]
  required_parameters = ["reason"]
  allowed_parameters = {
    "reason" = []
    "data" = []
  }
}

# Control response wrapping
path "secret/data/wrapped" {
  capabilities = ["read"]
  min_wrapping_ttl = "1m"
  max_wrapping_ttl = "90m"
}

Policy Management Commands

# Write a policy
vault policy write my-policy my-policy.hcl

# Read a policy
vault policy read my-policy

# List all policies
vault policy list

# Delete a policy
vault policy delete my-policy

# Format policy file
vault policy fmt my-policy.hcl

# Test a policy (requires sudo)
vault token capabilities secret/myapp/config

Built-in Policies

# Default policy - attached to all tokens
vault policy read default

# Root policy - superuser access (cannot be modified)
vault policy read root

# Create admin policy
cat > admin-policy.hcl << 'EOF'
# Manage secrets engines
path "sys/mounts/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

# Manage auth methods
path "sys/auth/*" {
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

# Manage policies
path "sys/policies/acl/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

# List policies
path "sys/policies/acl" {
  capabilities = ["list"]
}

# Read system health
path "sys/health" {
  capabilities = ["read", "sudo"]
}
EOF

vault policy write admin admin-policy.hcl

Dynamic Secrets

Key Concepts

  • Dynamic Secrets: Credentials generated on-demand with automatic expiration
  • Lease: Time-bound validity period for dynamic secrets
  • Revocation: Automatic or manual invalidation of credentials
  • Rotation: Automatic renewal of credentials

Database Dynamic Secrets

# MySQL dynamic credentials
vault write database/config/mysql-db \
    plugin_name=mysql-database-plugin \
    connection_url="{{username}}:{{password}}@tcp(127.0.0.1:3306)/" \
    allowed_roles="readonly,readwrite" \
    username="vault" \
    password="vaultpassword"

vault write database/roles/readonly \
    db_name=mysql-db \
    creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; \
        GRANT SELECT ON *.* TO '{{name}}'@'%';" \
    default_ttl="1h" \
    max_ttl="24h"

# Generate credentials
vault read database/creds/readonly

# Output:
# Key                Value
# ---                -----
# lease_id           database/creds/readonly/abcd1234
# lease_duration     1h
# lease_renewable    true
# password           A1a-xxxxxxxxxxxxxx
# username           v-token-readonly-xxxxxxxxxx

AWS Dynamic Secrets

# Enable AWS secrets engine
vault secrets enable aws

# Configure root credentials
vault write aws/config/root \
    access_key=AKIAIOSFODNN7EXAMPLE \
    secret_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \
    region=eu-west-1

# Create IAM user role
vault write aws/roles/my-role \
    credential_type=iam_user \
    policy_document=-<<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "*"
    }
  ]
}
EOF

# Create assumed role
vault write aws/roles/assumed-role \
    credential_type=assumed_role \
    role_arns=arn:aws:iam::123456789012:role/MyRole

# Generate credentials
vault read aws/creds/my-role

Lease Management

# List all leases
vault list sys/leases/lookup/database/creds/my-role

# Lookup lease information
vault lease lookup database/creds/my-role/abcd1234

# Renew a lease
vault lease renew database/creds/my-role/abcd1234
vault lease renew -increment=1h database/creds/my-role/abcd1234

# Revoke a specific lease
vault lease revoke database/creds/my-role/abcd1234

# Revoke all leases for a path
vault lease revoke -prefix database/creds/my-role

# Force revoke (skip backend cleanup)
vault lease revoke -force database/creds/my-role/abcd1234

Secret Rotation

Key Concepts

  • Static Rotation: Manual or scheduled rotation of existing credentials
  • Automatic Rotation: Vault automatically rotates credentials on a schedule
  • Root Rotation: Rotating the credentials Vault uses to connect to backends

Database Root Credential Rotation

# Rotate root credentials (Vault manages new password)
vault write -force database/rotate-root/my-postgresql-database

# Configure static role with rotation
vault write database/static-roles/my-static-role \
    db_name=my-postgresql-database \
    rotation_statements="ALTER USER \"{{name}}\" WITH PASSWORD '{{password}}';" \
    username="existing-db-user" \
    rotation_period=86400

# Get static credentials
vault read database/static-creds/my-static-role

# Force rotation
vault write -force database/rotate-role/my-static-role

PKI Certificate Rotation

# Rotate intermediate CA
vault write pki_int/intermediate/generate/internal \
    common_name="example.com Intermediate Authority" \
    | vault write pki/root/sign-intermediate \
    csr=- \
    format=pem_bundle \
    ttl=43800h

# Set signed certificate
vault write pki_int/intermediate/set-signed \
    certificate=@signed_certificate.pem

# Tidy up expired certificates
vault write pki/tidy \
    tidy_cert_store=true \
    tidy_revoked_certs=true \
    safety_buffer=72h

Token Rotation

# Rotate accessor (invalidates old token)
vault token create -policy="my-policy" -renewable=true

# Auto-renew tokens in applications
while true; do
    vault token renew -increment=1h
    sleep 3000  # Renew before expiry
done

CLI Essentials

Basic Operations

# Set Vault address
export VAULT_ADDR='https://vault.example.com:8200'

# Set token (not recommended for production)
# Service tokens are prefixed hvs. (s. on Vault < 1.10)
export VAULT_TOKEN='hvs.xxxxxxxxxx'

# Login interactively
vault login

# Check Vault status
vault status

# View help
vault path-help secret/
vault path-help sys/mounts

Read Operations

# Read a secret
vault read secret/myapp/config

# Read specific field
vault read -field=password secret/myapp/config

# Output as JSON
vault read -format=json secret/myapp/config

# Output as YAML
vault read -format=yaml secret/myapp/config

# Read with jq processing
vault read -format=json secret/myapp/config | jq -r '.data.data.password'

Write Operations

# Write key-value pairs
vault write secret/myapp/config username="admin" password="secret"

# Write from file
vault write secret/myapp/config @data.json

# Write from stdin
echo '{"username": "admin", "password": "secret"}' | vault write secret/myapp/config -

# Force write (no input)
vault write -force sys/leases/revoke-prefix/database/

# Write with output
vault write -format=json auth/approle/login role_id="xxx" secret_id="yyy"

Delete and List Operations

# Delete a secret
vault delete secret/myapp/config

# List secrets
vault list secret/
vault list -format=json secret/

# List with detailed output
vault list -detailed auth/token/accessors

Advanced CLI Usage

# Wrap response
vault read -wrap-ttl=10m secret/myapp/config

# Unwrap response
vault unwrap <wrapping_token>

# Use namespaces (Enterprise)
vault read -namespace=team1 secret/myapp/config
export VAULT_NAMESPACE=team1

# Enable audit logging
vault audit enable file file_path=/var/log/vault/audit.log

# Seal Vault (emergency)
vault operator seal

# Unseal Vault
vault operator unseal <key>

# Generate new unseal keys
vault operator rekey -init -key-shares=5 -key-threshold=3

Integration Patterns

Kubernetes Integration

HashiCorp VaultKubernetes ClusterApplication PodService AccountVault Init ContainerVault Agent SidecarVault APIKubernetes AuthSecret EngineHashiCorp VaultKubernetes ClusterApplication PodService AccountVault Init ContainerVault Agent SidecarVault APIKubernetes AuthSecret Engine

Vault Agent Injector

# Deployment with Vault Agent annotations
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  template:
    metadata:
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/role: "myapp"
        vault.hashicorp.com/agent-inject-secret-config: "secret/data/myapp/config"
        vault.hashicorp.com/agent-inject-template-config: |
          {{- with secret "secret/data/myapp/config" -}}
          export DB_USER="{{ .Data.data.username }}"
          export DB_PASS="{{ .Data.data.password }}"
          {{- end }}
    spec:
      serviceAccountName: myapp-sa
      containers:
        - name: myapp
          image: myapp:latest
          command: ["/bin/sh", "-c", "source /vault/secrets/config && ./start.sh"]

External Secrets Operator

# SecretStore for Vault
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: vault-backend
spec:
  provider:
    vault:
      server: "https://vault.example.com:8200"
      path: "secret"
      version: "v2"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "external-secrets"
          serviceAccountRef:
            name: "external-secrets-sa"

---
# ExternalSecret
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: myapp-secrets
spec:
  refreshInterval: "1h"
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: myapp-secrets
  data:
    - secretKey: username
      remoteRef:
        key: secret/myapp/config
        property: username
    - secretKey: password
      remoteRef:
        key: secret/myapp/config
        property: password

CI/CD Integration

GitHub Actions

name: Deploy with Vault Secrets

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read

    steps:
      - uses: actions/checkout@v4

      - name: Import Secrets
        uses: hashicorp/vault-action@v2
        with:
          url: https://vault.example.com:8200
          method: jwt
          role: github-actions
          secrets: |
            secret/data/myapp/config username | DB_USER ;
            secret/data/myapp/config password | DB_PASS ;
            secret/data/myapp/config api_key | API_KEY

      - name: Deploy Application
        run: |
          echo "Deploying with secrets..."
          ./deploy.sh
        env:
          DB_USER: ${{ env.DB_USER }}
          DB_PASS: ${{ env.DB_PASS }}

GitLab CI

# .gitlab-ci.yml
variables:
  VAULT_ADDR: https://vault.example.com:8200

deploy:
  image: hashicorp/vault:latest
  script:
    - export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=gitlab-ci jwt=$CI_JOB_JWT)"
    - export DB_PASS=$(vault kv get -field=password secret/myapp/config)
    - ./deploy.sh
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://vault.example.com

Jenkins Pipeline

pipeline {
    agent any

    environment {
        VAULT_ADDR = 'https://vault.example.com:8200'
    }

    stages {
        stage('Retrieve Secrets') {
            steps {
                withVault(
                    configuration: [
                        vaultUrl: "${VAULT_ADDR}",
                        vaultCredentialId: 'vault-approle'
                    ],
                    vaultSecrets: [
                        [
                            path: 'secret/myapp/config',
                            secretValues: [
                                [envVar: 'DB_USER', vaultKey: 'username'],
                                [envVar: 'DB_PASS', vaultKey: 'password']
                            ]
                        ]
                    ]
                ) {
                    sh './deploy.sh'
                }
            }
        }
    }
}

Application Integration

Python (hvac)

import hvac

# Token authentication
client = hvac.Client(
    url='https://vault.example.com:8200',
    token='hvs.xxxxxxxxxx'
)

# AppRole authentication
client = hvac.Client(url='https://vault.example.com:8200')
client.auth.approle.login(
    role_id='role-id',
    secret_id='secret-id'
)

# Read secret
secret = client.secrets.kv.v2.read_secret_version(
    path='myapp/config',
    mount_point='secret'
)
username = secret['data']['data']['username']
password = secret['data']['data']['password']

# Write secret
client.secrets.kv.v2.create_or_update_secret(
    path='myapp/config',
    secret={'username': 'admin', 'password': 'newpass'},
    mount_point='secret'
)

# Generate dynamic database credentials
creds = client.secrets.database.generate_credentials(
    name='my-role',
    mount_point='database'
)
db_user = creds['data']['username']
db_pass = creds['data']['password']

Go

package main

import (
    "context"
    "fmt"
    "log"

    vault "github.com/hashicorp/vault/api"
)

func main() {
    config := vault.DefaultConfig()
    config.Address = "https://vault.example.com:8200"

    client, err := vault.NewClient(config)
    if err != nil {
        log.Fatal(err)
    }

    // Set token
    client.SetToken("hvs.xxxxxxxxxx")

    // Read secret
    secret, err := client.KVv2("secret").Get(
        context.Background(),
        "myapp/config",
    )
    if err != nil {
        log.Fatal(err)
    }

    username := secret.Data["username"].(string)
    password := secret.Data["password"].(string)

    fmt.Printf("Username: %s\n", username)
}

Node.js

const vault = require('node-vault')({
  apiVersion: 'v1',
  endpoint: 'https://vault.example.com:8200',
  token: 'hvs.xxxxxxxxxx'
});

// Read secret (KV v2)
async function getSecret() {
  const result = await vault.read('secret/data/myapp/config');
  const { username, password } = result.data.data;
  return { username, password };
}

// AppRole login
async function loginAppRole(roleId, secretId) {
  const result = await vault.approleLogin({
    role_id: roleId,
    secret_id: secretId
  });
  vault.token = result.auth.client_token;
}

// Write secret
async function writeSecret(path, data) {
  await vault.write(`secret/data/${path}`, {
    data: data
  });
}

Quick Reference

Command Description
vault status Check Vault server status and seal state
vault login Authenticate to Vault
vault token lookup Display information about current token
vault kv get secret/path Read a secret from KV store
vault kv put secret/path key=value Write a secret to KV store
vault kv list secret/ List secrets at a path
vault kv delete secret/path Delete a secret
vault secrets list List all enabled secret engines
vault secrets enable -path=name type Enable a secret engine
vault auth list List all enabled auth methods
vault auth enable type Enable an auth method
vault policy list List all policies
vault policy write name file.hcl Create or update a policy
vault policy read name Read a policy
vault lease revoke lease_id Revoke a lease
vault lease renew lease_id Renew a lease
vault operator seal Seal the Vault
vault operator unseal Unseal the Vault
vault audit enable type Enable an audit device
vault read -format=json path Read with JSON output
vault write -force path Write without input data

Environment Variables

Variable Description
VAULT_ADDR Vault server address
VAULT_TOKEN Authentication token
VAULT_NAMESPACE Namespace (Enterprise)
VAULT_CACERT Path to CA certificate
VAULT_CLIENT_CERT Path to client certificate
VAULT_CLIENT_KEY Path to client private key
VAULT_SKIP_VERIFY Skip TLS verification (not recommended)
VAULT_FORMAT Output format (json, yaml, table)

Common Issues and Solutions

Issue: "permission denied" Error

Symptoms: Unable to read or write secrets despite being authenticated.

Solutions:

# Check your current token capabilities
vault token capabilities secret/myapp/config

# Verify token policies
vault token lookup

# Check policy content
vault policy read my-policy

# Ensure path matches exactly (including trailing slash for list)
vault kv list secret/myapp/    # Note trailing slash

Issue: Token Expired or Invalid

Symptoms: "token expired" or "missing client token" errors.

Solutions:

# Check token TTL
vault token lookup

# Renew token before expiry
vault token renew

# Re-authenticate
vault login -method=approle role_id=$ROLE_ID secret_id=$SECRET_ID

# Use renewable tokens
vault token create -policy="my-policy" -renewable=true -ttl=1h

Issue: Secret Not Found

Symptoms: "no value found at path" error.

Solutions:

# Check if using KV v1 or v2 (paths differ)
# KV v1: secret/myapp/config
# KV v2: secret/data/myapp/config (data prefix)

vault kv get secret/myapp/config  # CLI handles versioning

# List to verify path exists
vault kv list secret/myapp/

# Check for soft-deleted secrets (KV v2)
vault kv metadata get secret/myapp/config
vault kv undelete -versions=1 secret/myapp/config

Issue: Vault Sealed

Symptoms: "Vault is sealed" error after restart.

Solutions:

# Check seal status
vault status

# Unseal with threshold keys
vault operator unseal <key-1>
vault operator unseal <key-2>
vault operator unseal <key-3>

# Configure auto-unseal (recommended for production)
# In vault.hcl:
seal "awskms" {
  region     = "eu-west-1"
  kms_key_id = "alias/vault-unseal"
}

Issue: Certificate Errors

Symptoms: TLS handshake or certificate verification failures.

Solutions:

# Specify CA certificate
export VAULT_CACERT=/path/to/ca.crt

# Or use environment variables
vault read -ca-cert=/path/to/ca.crt secret/myapp/config

# Skip verification (development only!)
export VAULT_SKIP_VERIFY=true

# Check certificate
openssl s_client -connect vault.example.com:8200 -CAfile ca.crt

Issue: Lease Not Renewable

Symptoms: "lease is not renewable" error.

Solutions:

# Check lease details
vault lease lookup <lease_id>

# Some dynamic secrets have max TTL limits
# Check role configuration
vault read database/roles/my-role

# Request new credentials instead of renewing
vault read database/creds/my-role

# Increase max_ttl in role if needed
vault write database/roles/my-role max_ttl=48h

Issue: High Availability Redirect

Symptoms: Requests redirected to standby node.

Solutions:

# Use the active node address
vault status  # Check if standby

# Configure client to follow redirects
export VAULT_MAX_RETRIES=5

# Use load balancer that routes to active node
# Or configure DNS with health checks

Issue: Audit Log Full

Symptoms: Vault stops responding when audit device is blocked.

Solutions:

# Vault blocks all operations if audit fails (security feature)
# Ensure audit log destination is available

# Rotate logs
logrotate /etc/logrotate.d/vault

# Add multiple audit devices for redundancy
vault audit enable file file_path=/var/log/vault/audit.log
vault audit enable syslog tag="vault"

# Check audit device status
vault audit list -detailed

Related Topics

The following topics would complement this HashiCorp Vault cheatsheet:

  1. Consul - Service discovery and configuration often used alongside Vault as a storage backend and for service mesh integration

  2. Kubernetes Secrets Management - Native Kubernetes secrets handling and comparison with external secret management solutions

  3. PKI and TLS Certificates - Deeper understanding of certificate authorities, certificate chains, and TLS configuration

  4. OAuth2 and OIDC - Authentication protocols used by Vault's OIDC auth method and JWT validation

  5. Terraform Vault Provider - Infrastructure as Code approach to managing Vault configuration, policies, and secret engines

  6. Security Compliance Frameworks - Understanding SOC2, PCI-DSS, and other compliance requirements that Vault helps address