Secret Management Expert
Expert in secret lifecycle management — storage, rotation, injection, and audit — across cloud and self-hosted infrastructure.
Activation Triggers
Activate on: "secret management", "Vault setup", "AWS Secrets Manager", "secret rotation", "SOPS encryption", "sealed secrets", "credential storage", "API key management", "least privilege secrets"
NOT for: Application auth flows → oauth-oidc-implementer | Network security → security-auditor | Encryption at rest → devops-automator
Quick Start
- Inventory secrets — catalog all credentials, API keys, certificates, and tokens
- Choose a backend — Vault for self-hosted, AWS Secrets Manager/GCP Secret Manager for cloud-native
- Implement injection — sidecar (Vault Agent), CSI driver, or init container pattern
- Enable rotation — automated rotation with zero-downtime credential swaps
- Audit and alert — log all secret access, alert on anomalous patterns
Core Capabilities
| Domain |
Technologies |
| Secret Stores |
HashiCorp Vault 1.18, AWS Secrets Manager, GCP Secret Manager, Azure Key Vault |
| Encryption |
SOPS 3.9, age, AWS KMS, GCP Cloud KMS, sealed-secrets |
| K8s Integration |
External Secrets Operator, Vault CSI Provider, Sealed Secrets controller |
| Rotation |
Vault dynamic secrets, AWS Lambda rotation, custom rotation functions |
| Audit |
Vault audit log, CloudTrail, access anomaly detection |
Architecture Patterns
External Secrets Operator (K8s Best Practice, 2026)
# ExternalSecret pulls from AWS Secrets Manager into K8s Secret
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: database-credentials
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: db-credentials # K8s Secret name
creationPolicy: Owner
data:
- secretKey: DB_PASSWORD
remoteRef:
key: prod/database/postgres
property: password
- secretKey: DB_USERNAME
remoteRef:
key: prod/database/postgres
property: username
Vault Dynamic Secrets (Zero Standing Credentials)
App requests credential → Vault generates ephemeral DB credential
├─ Credential has TTL (e.g., 1 hour)
├─ Vault creates DB user with scoped permissions
├─ App uses credential until near expiry
├─ Vault Agent auto-renews or rotates
└─ On expiry: Vault revokes DB user automatically
Result: No long-lived credentials exist. Every credential is:
- Unique to the requester
- Time-bounded
- Automatically revoked
- Fully audited
SOPS for Git-Encrypted Secrets
# Encrypt secrets file with age key (developer workflow)
sops --encrypt --age age1... secrets.yaml > secrets.enc.yaml
# Decrypt in CI/CD pipeline
export SOPS_AGE_KEY=$(vault kv get -field=age-key secret/ci/sops)
sops --decrypt secrets.enc.yaml > secrets.yaml
# .sops.yaml — defines encryption rules per path
creation_rules:
- path_regex: secrets\.yaml$
age: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
- path_regex: \.env\..*$
age: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
Anti-Patterns
- Secrets in environment variables at build time — Docker
ARG and ENV persist in image layers. Use runtime injection via sidecar, CSI driver, or entrypoint script.
- Shared service accounts — one credential used by multiple services. Use per-service identities with scoped permissions so compromise is isolated.
- No rotation — static credentials that never change. Implement automated rotation with overlap periods so active credentials always work.
- Secrets in Git — even in
.env.example with placeholder values that get real values committed. Use SOPS, sealed-secrets, or External Secrets Operator. Add .env* to .gitignore.
- Manual secret distribution — passing credentials via Slack, email, or shared drives. Use a secret store with RBAC and audit logging.
Quality Checklist
[ ] All secrets stored in a dedicated secret store (not config files)
[ ] No secrets in Docker image layers, Git history, or CI logs
[ ] Automated rotation enabled for database credentials
[ ] Secret access logged and auditable (Vault audit, CloudTrail)
[ ] Least privilege: each service has scoped access to only its secrets
[ ] SOPS or sealed-secrets used for any secrets committed to Git
[ ] Dynamic secrets preferred over static credentials
[ ] Secret TTLs set — no indefinite credentials
[ ] Emergency revocation procedure documented and tested
[ ] CI/CD uses short-lived tokens (OIDC federation), not long-lived keys
[ ] Developers cannot access production secrets from local machines
[ ] Secret sprawl inventory maintained and reviewed quarterly
1---2name: secret-management-expert3description: Secret lifecycle management with Vault, AWS Secrets Manager, and rotation automation. Activate on: secret management, HashiCorp Vault, AWS Secrets Manager, secret rotation, SOPS, sealed secrets, credential management, API key storage, least privilege. NOT for: application auth flows (use oauth-oidc-implementer), network security (use security-auditor), encryption at rest (use devops-automator).4license: Apache-2.05---6
7# Secret Management Expert
8
9Expert in secret lifecycle management — storage, rotation, injection, and audit — across cloud and self-hosted infrastructure.
10
11## Activation Triggers
12
13**Activate on:** "secret management", "Vault setup", "AWS Secrets Manager", "secret rotation", "SOPS encryption", "sealed secrets", "credential storage", "API key management", "least privilege secrets"
14
15**NOT for:** Application auth flows → `oauth-oidc-implementer` | Network security → `security-auditor` | Encryption at rest → `devops-automator`
16
17## Quick Start
18
191. **Inventory secrets** — catalog all credentials, API keys, certificates, and tokens
202. **Choose a backend** — Vault for self-hosted, AWS Secrets Manager/GCP Secret Manager for cloud-native
213. **Implement injection** — sidecar (Vault Agent), CSI driver, or init container pattern
224. **Enable rotation** — automated rotation with zero-downtime credential swaps
235. **Audit and alert** — log all secret access, alert on anomalous patterns
24
25## Core Capabilities
26
27| Domain | Technologies |
28|--------|-------------|
29| **Secret Stores** | HashiCorp Vault 1.18, AWS Secrets Manager, GCP Secret Manager, Azure Key Vault |
30| **Encryption** | SOPS 3.9, age, AWS KMS, GCP Cloud KMS, sealed-secrets |
31| **K8s Integration** | External Secrets Operator, Vault CSI Provider, Sealed Secrets controller |
32| **Rotation** | Vault dynamic secrets, AWS Lambda rotation, custom rotation functions |
33| **Audit** | Vault audit log, CloudTrail, access anomaly detection |
34
35## Architecture Patterns
36
37### External Secrets Operator (K8s Best Practice, 2026)
38
39```yaml
40# ExternalSecret pulls from AWS Secrets Manager into K8s Secret
41apiVersion: external-secrets.io/v1
42kind: ExternalSecret
43metadata:
44 name: database-credentials
45spec:
46 refreshInterval: 1h
47 secretStoreRef:
48 name: aws-secrets-manager
49 kind: ClusterSecretStore
50 target:
51 name: db-credentials # K8s Secret name
52 creationPolicy: Owner
53 data:
54 - secretKey: DB_PASSWORD
55 remoteRef:
56 key: prod/database/postgres
57 property: password
58 - secretKey: DB_USERNAME
59 remoteRef:
60 key: prod/database/postgres
61 property: username
62```
63
64### Vault Dynamic Secrets (Zero Standing Credentials)
65
66```
67App requests credential → Vault generates ephemeral DB credential
68 ├─ Credential has TTL (e.g., 1 hour)
69 ├─ Vault creates DB user with scoped permissions
70 ├─ App uses credential until near expiry
71 ├─ Vault Agent auto-renews or rotates
72 └─ On expiry: Vault revokes DB user automatically
73
74Result: No long-lived credentials exist. Every credential is:
75 - Unique to the requester
76 - Time-bounded
77 - Automatically revoked
78 - Fully audited
79```
80
81### SOPS for Git-Encrypted Secrets
82
83```bash
84# Encrypt secrets file with age key (developer workflow)
85sops --encrypt --age age1... secrets.yaml > secrets.enc.yaml
86
87# Decrypt in CI/CD pipeline
88export SOPS_AGE_KEY=$(vault kv get -field=age-key secret/ci/sops)
89sops --decrypt secrets.enc.yaml > secrets.yaml
90
91# .sops.yaml — defines encryption rules per path
92creation_rules:
93 - path_regex: secrets\.yaml$
94 age: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
95 - path_regex: \.env\..*$
96 age: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
97```
98
99## Anti-Patterns
100
1011. **Secrets in environment variables at build time** — Docker `ARG` and `ENV` persist in image layers. Use runtime injection via sidecar, CSI driver, or entrypoint script.
1022. **Shared service accounts** — one credential used by multiple services. Use per-service identities with scoped permissions so compromise is isolated.
1033. **No rotation** — static credentials that never change. Implement automated rotation with overlap periods so active credentials always work.
1044. **Secrets in Git** — even in `.env.example` with placeholder values that get real values committed. Use SOPS, sealed-secrets, or External Secrets Operator. Add `.env*` to `.gitignore`.
1055. **Manual secret distribution** — passing credentials via Slack, email, or shared drives. Use a secret store with RBAC and audit logging.
106
107## Quality Checklist
108
109```
110[ ] All secrets stored in a dedicated secret store (not config files)
111[ ] No secrets in Docker image layers, Git history, or CI logs
112[ ] Automated rotation enabled for database credentials
113[ ] Secret access logged and auditable (Vault audit, CloudTrail)
114[ ] Least privilege: each service has scoped access to only its secrets
115[ ] SOPS or sealed-secrets used for any secrets committed to Git
116[ ] Dynamic secrets preferred over static credentials
117[ ] Secret TTLs set — no indefinite credentials
118[ ] Emergency revocation procedure documented and tested
119[ ] CI/CD uses short-lived tokens (OIDC federation), not long-lived keys
120[ ] Developers cannot access production secrets from local machines
121[ ] Secret sprawl inventory maintained and reviewed quarterly
122```