ancoleman/managing-secrets
Managing secrets (API keys, database credentials, certificates) with Vault, cloud providers, and Kubernetes. Use when storing sensitive data, rotating credentials, syncing secrets to Kubernetes, implementing dynamic secrets, or scanning code for leaked secrets.
npx skills add https://github.com/ancoleman/ai-design-components --skill managing-secrets
Secure storage, rotation, and delivery of secrets (API keys, database credentials, TLS certificates) for applications and infrastructure.
Use when:
| Scenario | Primary Choice | Alternative |
|----------|----------------|-------------|
| Kubernetes + Multi-Cloud | Vault + ESO | Cloud Secret Manager + ESO |
| Kubernetes + Single Cloud | Cloud Secret Manager + ESO | Vault + ESO |
| Serverless (AWS Lambda) | AWS Secrets Manager | AWS Parameter Store |
| Multi-Cloud Enterprise | HashiCorp Vault | Doppler (SaaS) |
| Small Team (<10 apps) | Doppler, Infisical | 1Password Secrets Automation |
| GitOps-Centric | SOPS (git-encrypted) | Sealed Secrets (K8s-only) |
Decision Tree:
| Secret Type | Use Dynamic? | TTL | Solution |
|-------------|-------------|-----|----------|
| Database credentials | YES | 1 hour | Vault DB engine |
| Cloud IAM (AWS/GCP) | YES | 15 min | Vault cloud engine |
| SSH/RDP access | YES | 5 min | Vault SSH engine |
| TLS certificates | YES | 24 hours | Vault PKI / cert-manager |
| Third-party API keys | NO | Quarterly | Vault KV v2 (manual rotation) |
| Method | Use Case | Rotation | Restart Required |
|--------|----------|----------|------------------|
| External Secrets Operator | Static secrets, periodic sync | Polling (1h) | Yes |
| Secrets Store CSI Driver | File-based, watch rotation | inotify | No |
| Vault Secrets Operator | Vault-specific, dynamic | Automatic renewal | Optional |
# Create secret
vault kv put secret/myapp/config api_key=sk_live_EXAMPLE
# Read secret
vault kv get secret/myapp/config
# List versions
vault kv metadata get secret/myapp/config
# Configure PostgreSQL
vault write database/config/postgres \
plugin_name=postgresql-database-plugin \
connection_url="postgresql://{{username}}:{{password}}@postgres:5432/mydb"
# Create role
vault write database/roles/app-role \
db_name=postgres \
creation_statements="CREATE ROLE \"{{name}}\"..." \
default_ttl="1h"
# Generate credentials
vault read database/creds/app-role
For detailed Vault architecture, see references/vault-architecture.md.
Syncs secrets from 30+ providers to Kubernetes Secrets.
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-backend
spec:
provider:
vault:
server: "https://vault.example.com"
auth:
kubernetes:
role: "app-role"
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: database-credentials
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
target:
name: db-credentials
data:
- secretKey: password
remoteRef:
key: secret/data/database/config
Kubernetes-native Vault integration with automatic lease renewal.
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultDynamicSecret
metadata:
name: postgres-creds
spec:
vaultAuthRef: vault-auth
mount: database
path: creds/app-role
renewalPercent: 67 # Renew at 67% of TTL
destination:
name: dynamic-db-creds
For ESO vs CSI vs VSO comparison, see references/kubernetes-integration.md.
Vault auto-generates credentials with short TTL:
Using cert-manager + Vault PKI:
For detailed rotation workflows, see references/rotation-patterns.md.
import hvac
client = hvac.Client(url='https://vault.example.com')
client.auth.kubernetes(role='app-role', jwt=jwt)
# Fetch dynamic credentials
response = client.secrets.database.generate_credentials(name='postgres-role')
username = response['data']['username']
password = response['data']['password']
import vault "github.com/hashicorp/vault/api"
client, _ := vault.NewClient(vault.DefaultConfig())
k8sAuth, _ := auth.NewKubernetesAuth("app-role")
client.Auth().Login(context.Background(), k8sAuth)
secret, _ := client.Logical().Read("database/creds/postgres-role")
import vault from 'node-vault';
const client = vault({ endpoint: 'https://vault.example.com' });
await client.kubernetesLogin({ role: 'app-role', jwt });
const response = await client.read('database/creds/postgres-role');
For complete examples, see examples/dynamic-db-credentials/.
# Install Gitleaks
brew install gitleaks
# Run on staged files
gitleaks protect --staged --verbose
Pre-commit hook prevents secrets from being committed.
For setup, see examples/secret-scanning/pre-commit.
# GitHub Actions
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
When a secret is leaked:
For detailed remediation, see references/secret-scanning.md.
User password → PBKDF2 → encryption key → encrypt secret → send to server
Server stores only encrypted blobs (cannot decrypt).
Split secret into N shares, require M to reconstruct (e.g., 3 of 5).
# Initialize Vault with Shamir shares
vault operator init -key-shares=5 -key-threshold=3
# Unseal requires 3 of 5 key shares
vault operator unseal <KEY_1>
vault operator unseal <KEY_2>
vault operator unseal <KEY_3>
For implementations, see references/zero-knowledge.md.
| Library | Use Case | Trust Score |
|---------|----------|-------------|
| HashiCorp Vault | Enterprise, multi-cloud | High (73.3/100) |
| External Secrets Operator | Kubernetes integration | High (85.0/100) |
| AWS Secrets Manager | AWS workloads | High |
| GCP Secret Manager | GCP workloads | High |
| Azure Key Vault | Azure workloads | High |
| Library | Use Case | Trust Score |
|---------|----------|-------------|
| Gitleaks | Pre-commit, CI/CD | High (89.9/100) |
| TruffleHog | Git history scanning | Medium |
| Language | Library | Version |
|----------|---------|---------|
| Python | hvac | 2.2.0+ |
| Go | vault/api | Latest |
| TypeScript | node-vault | 0.10.2+ |
| Rust | vaultrs | 0.7+ |
For step-by-step guide, see examples/vault-eso-setup/.
For implementation, see examples/dynamic-db-credentials/.
For setup, see examples/secret-scanning/.
Environment variables visible in process lists.
Solution: Use file-based secrets (Kubernetes volumes, CSI driver).
Base64 is not encryption.
Solution: Use External Secrets Operator.
Stale credentials increase breach risk.
Solution: Use dynamic secrets or automate rotation.
Unlimited permissions.
Solution: Use auth methods with least privilege policies.
references/vault-architecture.md - Vault internals, HA setup, policiesreferences/kubernetes-integration.md - ESO, CSI driver, VSO comparisonreferences/rotation-patterns.md - Detailed rotation workflowsreferences/secret-scanning.md - Gitleaks, remediation proceduresreferences/zero-knowledge.md - E2EE, Shamir's secret sharingreferences/cloud-providers.md - AWS, GCP, Azure secret managersexamples/vault-eso-setup/ - Complete Kubernetes setupexamples/dynamic-db-credentials/ - Multi-language examplesexamples/secret-scanning/ - Pre-commit hooks, CI/CDscripts/setup_vault.sh - Automated Vault installationTake ancoleman/managing-secrets from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference brew.
Without those the skill loads but fails at the first command.