Secrets Management
by @brandonwise
Securely store, manage, rotate, and integrate secrets (API keys, passwords, certificates) in CI/CD pipelines using Vault, AWS Secrets Manager, and native tools.
clawhub install secrets-managementπ About This Skill
Secrets Management
Secure secrets management for CI/CD pipelines using Vault, AWS Secrets Manager, and native platform solutions.
Description
USE WHEN:
DON'T USE WHEN:
Secrets Management Tools Comparison
| Tool | Best For | Key Features | |------|----------|--------------| | HashiCorp Vault | Enterprise, multi-cloud | Dynamic secrets, rotation, audit logging | | AWS Secrets Manager | AWS-native workloads | RDS integration, auto-rotation | | Azure Key Vault | Azure workloads | HSM-backed, certificate management | | Google Secret Manager | GCP workloads | Versioning, IAM integration | | GitHub Secrets | GitHub Actions | Simple, per-repo/org/environment | | GitLab CI Variables | GitLab CI | Protected branches, masked variables |
HashiCorp Vault
Setup
# Start Vault dev server
vault server -devSet environment
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='root'Enable secrets engine
vault secrets enable -path=secret kv-v2Store secret
vault kv put secret/database/config username=admin password=secret
GitHub Actions with Vault
name: Deploy with Vault Secretson: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Import Secrets from Vault
uses: hashicorp/vault-action@v2
with:
url: https://vault.example.com:8200
token: ${{ secrets.VAULT_TOKEN }}
secrets: |
secret/data/database username | DB_USERNAME ;
secret/data/database password | DB_PASSWORD ;
secret/data/api key | API_KEY
- name: Use secrets
run: |
echo "Connecting to database as $DB_USERNAME"
# Use $DB_PASSWORD, $API_KEY
GitLab CI with Vault
deploy:
image: vault:latest
before_script:
- export VAULT_ADDR=https://vault.example.com:8200
- export VAULT_TOKEN=$VAULT_TOKEN
- apk add curl jq
script:
- |
DB_PASSWORD=$(vault kv get -field=password secret/database/config)
API_KEY=$(vault kv get -field=key secret/api/credentials)
echo "Deploying with secrets..."
AWS Secrets Manager
Store Secret
aws secretsmanager create-secret \
--name production/database/password \
--secret-string "super-secret-password"
Retrieve in GitHub Actions
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-west-2name: Get secret from AWS
run: |
SECRET=$(aws secretsmanager get-secret-value \
--secret-id production/database/password \
--query SecretString \
--output text)
echo "::add-mask::$SECRET"
echo "DB_PASSWORD=$SECRET" >> $GITHUB_ENVname: Use secret
run: ./deploy.sh # $DB_PASSWORD available
Terraform Integration
data "aws_secretsmanager_secret_version" "db_password" {
secret_id = "production/database/password"
}resource "aws_db_instance" "main" {
allocated_storage = 100
engine = "postgres"
instance_class = "db.t3.large"
username = "admin"
password = jsondecode(data.aws_secretsmanager_secret_version.db_password.secret_string)["password"]
}
Kubernetes: External Secrets Operator
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-backend
namespace: production
spec:
provider:
vault:
server: "https://vault.example.com:8200"
path: "secret"
version: "v2"
auth:
kubernetes:
mountPath: "kubernetes"
role: "production"
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: database-credentials
namespace: production
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: database-credentials
creationPolicy: Owner
data:
- secretKey: username
remoteRef:
key: database/config
property: username
- secretKey: password
remoteRef:
key: database/config
property: password
Secret Rotation
Automated (AWS Lambda)
import boto3
import jsondef lambda_handler(event, context):
client = boto3.client('secretsmanager')
# Get current secret
response = client.get_secret_value(SecretId='my-secret')
current_secret = json.loads(response['SecretString'])
# Generate new password
new_password = generate_strong_password()
# Update database password
update_database_password(new_password)
# Update secret
client.put_secret_value(
SecretId='my-secret',
SecretString=json.dumps({
'username': current_secret['username'],
'password': new_password
})
)
return {'statusCode': 200}
Manual Rotation Process
1. Generate new secret 2. Update secret in secret store 3. Update applications to use new secret 4. Verify functionality 5. Revoke old secret
Secret Scanning
Pre-commit Hook
#!/bin/bash
.git/hooks/pre-commit
Check for secrets with TruffleHog
docker run --rm -v "$(pwd):/repo" \
trufflesecurity/trufflehog:latest \
filesystem --directory=/repoif [ $? -ne 0 ]; then
echo "β Secret detected! Commit blocked."
exit 1
fi
CI/CD Secret Scanning
secret-scan:
stage: security
image: trufflesecurity/trufflehog:latest
script:
- trufflehog filesystem .
allow_failure: false
Best Practices
1. Never commit secrets to Git 2. Use different secrets per environment 3. Rotate secrets regularly (90 days max) 4. Implement least-privilege access 5. Enable audit logging 6. Use secret scanning (GitGuardian, TruffleHog) 7. Mask secrets in logs 8. Encrypt secrets at rest 9. Use short-lived tokens when possible 10. Document secret requirements
Related Skills
vulnerability-scanner - For detecting exposed secrets in codeapi-security - For securing API credentialsβοΈ Configuration
# Start Vault dev server
vault server -devSet environment
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='root'Enable secrets engine
vault secrets enable -path=secret kv-v2Store secret
vault kv put secret/database/config username=admin password=secret
GitHub Actions with Vault
name: Deploy with Vault Secretson: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Import Secrets from Vault
uses: hashicorp/vault-action@v2
with:
url: https://vault.example.com:8200
token: ${{ secrets.VAULT_TOKEN }}
secrets: |
secret/data/database username | DB_USERNAME ;
secret/data/database password | DB_PASSWORD ;
secret/data/api key | API_KEY
- name: Use secrets
run: |
echo "Connecting to database as $DB_USERNAME"
# Use $DB_PASSWORD, $API_KEY
GitLab CI with Vault
deploy:
image: vault:latest
before_script:
- export VAULT_ADDR=https://vault.example.com:8200
- export VAULT_TOKEN=$VAULT_TOKEN
- apk add curl jq
script:
- |
DB_PASSWORD=$(vault kv get -field=password secret/database/config)
API_KEY=$(vault kv get -field=key secret/api/credentials)
echo "Deploying with secrets..."
π Tips & Best Practices
1. Never commit secrets to Git 2. Use different secrets per environment 3. Rotate secrets regularly (90 days max) 4. Implement least-privilege access 5. Enable audit logging 6. Use secret scanning (GitGuardian, TruffleHog) 7. Mask secrets in logs 8. Encrypt secrets at rest 9. Use short-lived tokens when possible 10. Document secret requirements