hashicorp-vault

star 32

Manage secrets and PKI with HashiCorp Vault. Configure secret engines, authentication methods, and policies. Use when implementing centralized secrets management, dynamic credentials, or certificate management.

BagelHole By BagelHole schedule Updated 1/27/2026

name: hashicorp-vault description: Manage secrets and PKI with HashiCorp Vault. Configure secret engines, authentication methods, and policies. Use when implementing centralized secrets management, dynamic credentials, or certificate management. license: MIT metadata: author: devops-skills version: "1.0"

HashiCorp Vault

Centrally manage secrets, encryption, and access with HashiCorp Vault.

When to Use This Skill

Use this skill when:

  • Centralizing secrets management
  • Implementing dynamic credentials
  • Managing PKI and certificates
  • Encrypting sensitive data
  • Meeting compliance requirements

Prerequisites

  • Vault server (dev or production)
  • Vault CLI installed
  • Network access to Vault

Quick Start

Development Server

# Start dev server
vault server -dev

# Set environment
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='root'

# Verify connection
vault status

Production Deployment

# config.hcl
storage "raft" {
  path = "/opt/vault/data"
  node_id = "vault-1"
}

listener "tcp" {
  address = "0.0.0.0:8200"
  tls_cert_file = "/opt/vault/tls/vault.crt"
  tls_key_file = "/opt/vault/tls/vault.key"
}

api_addr = "https://vault.example.com:8200"
cluster_addr = "https://vault.example.com:8201"

ui = true
# Initialize Vault
vault operator init -key-shares=5 -key-threshold=3

# Unseal (run 3 times with different keys)
vault operator unseal <key-1>
vault operator unseal <key-2>
vault operator unseal <key-3>

# Login
vault login <root-token>

Secret Engines

KV Secrets

# Enable KV v2
vault secrets enable -path=secret kv-v2

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

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

# Update secret
vault kv put secret/myapp/config \
  username="admin" \
  password="new-password"

# List secrets
vault kv list secret/

# Delete secret
vault kv delete secret/myapp/config

# Version history
vault kv metadata get secret/myapp/config

Database Secrets

# Enable database engine
vault secrets enable database

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

# Create role
vault write database/roles/readonly \
  db_name=postgresql \
  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"

# Get credentials
vault read database/creds/readonly

AWS Secrets

# Enable AWS engine
vault secrets enable aws

# Configure root credentials
vault write aws/config/root \
  access_key=AKIA... \
  secret_key=secret... \
  region=us-east-1

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

# Get credentials
vault read aws/creds/deploy

PKI Secrets

# Enable PKI engine
vault secrets enable pki
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 URLs
vault write pki/config/urls \
  issuing_certificates="https://vault.example.com:8200/v1/pki/ca" \
  crl_distribution_points="https://vault.example.com:8200/v1/pki/crl"

# Create role
vault write pki/roles/web-server \
  allowed_domains="example.com" \
  allow_subdomains=true \
  max_ttl="720h"

# Issue certificate
vault write pki/issue/web-server \
  common_name="web.example.com" \
  ttl="24h"

Authentication Methods

AppRole

# Enable AppRole
vault auth enable approle

# Create role
vault write auth/approle/role/myapp \
  token_policies="myapp-policy" \
  token_ttl=1h \
  token_max_ttl=4h \
  secret_id_ttl=10m

# Get role ID
vault read auth/approle/role/myapp/role-id

# Generate secret ID
vault write -f auth/approle/role/myapp/secret-id

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

Kubernetes

# Enable Kubernetes auth
vault auth enable kubernetes

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

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

OIDC

# Enable OIDC auth
vault auth enable oidc

# Configure
vault write auth/oidc/config \
  oidc_discovery_url="https://accounts.google.com" \
  oidc_client_id="your-client-id" \
  oidc_client_secret="your-client-secret" \
  default_role="default"

# Create role
vault write auth/oidc/role/default \
  bound_audiences="your-client-id" \
  allowed_redirect_uris="http://localhost:8250/oidc/callback" \
  user_claim="sub" \
  policies="default"

Policies

Policy Definition

# myapp-policy.hcl
# Read secrets
path "secret/data/myapp/*" {
  capabilities = ["read", "list"]
}

# Database credentials
path "database/creds/myapp-db" {
  capabilities = ["read"]
}

# PKI certificates
path "pki/issue/web-server" {
  capabilities = ["create", "update"]
}

# Deny access to other secrets
path "secret/data/other/*" {
  capabilities = ["deny"]
}
# Create policy
vault policy write myapp myapp-policy.hcl

# List policies
vault policy list

# Read policy
vault policy read myapp

Application Integration

Python

import hvac

# Initialize client
client = hvac.Client(url='http://localhost:8200')

# AppRole authentication
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'
)
password = secret['data']['data']['password']

# Get database credentials
db_creds = client.secrets.database.generate_credentials(
    name='myapp-db'
)

Kubernetes Sidecar

apiVersion: v1
kind: Pod
metadata:
  name: myapp
  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_PASSWORD="{{ .Data.data.password }}"
      {{- end }}
spec:
  serviceAccountName: myapp
  containers:
    - name: myapp
      image: myapp:latest
      command: ["/bin/sh", "-c", "source /vault/secrets/config && ./start.sh"]

Common Issues

Issue: Sealed Vault

Problem: Vault is sealed after restart Solution: Implement auto-unseal with cloud KMS or HSM

Issue: Token Expired

Problem: Application token has expired Solution: Implement token renewal, use shorter-lived tokens

Issue: Permission Denied

Problem: Cannot access secrets Solution: Review policies, check token capabilities

Best Practices

  • Use short-lived tokens
  • Implement auto-unseal
  • Enable audit logging
  • Use namespaces for isolation
  • Rotate root tokens regularly
  • Implement least-privilege policies
  • Use dynamic secrets where possible
  • Regular backup and DR testing

Related Skills

Install via CLI
npx skills add https://github.com/BagelHole/DevOps-Security-Agent-Skills --skill hashicorp-vault
Repository Details
star Stars 32
call_split Forks 4
navigation Branch main
article Path SKILL.md
More from Creator