home / skills / aj-geddes / useful-ai-prompts / secrets-management

secrets-management skill

/skills/secrets-management

This skill helps you implement secure secrets management using Vault, AWS Secrets Manager, or Kubernetes Secrets, with rotation and auditing.

npx playbooks add skill aj-geddes/useful-ai-prompts --skill secrets-management

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
11.6 KB
---
name: secrets-management
description: Implement secrets management with HashiCorp Vault, AWS Secrets Manager, or Kubernetes Secrets for secure credential storage and rotation.
---

# Secrets Management

## Overview

Deploy and configure secure secrets management systems to store, rotate, and audit access to sensitive credentials, API keys, and certificates across your infrastructure.

## When to Use

- Database credentials management
- API key and token storage
- Certificate management
- SSH key distribution
- Credential rotation automation
- Audit and compliance logging
- Multi-environment secrets
- Encryption key management

## Implementation Examples

### 1. **HashiCorp Vault Setup**

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

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

api_addr     = "https://0.0.0.0:8200"
cluster_addr = "https://0.0.0.0:8201"

ui = true
```

### 2. **Vault Kubernetes Integration**

```yaml
# vault-kubernetes.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: vault-auth
  namespace: vault

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: vault-auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
  - kind: ServiceAccount
    name: vault-auth
    namespace: vault

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: vault
  namespace: vault
spec:
  replicas: 3
  serviceName: vault
  selector:
    matchLabels:
      app: vault
  template:
    metadata:
      labels:
        app: vault
    spec:
      serviceAccountName: vault-auth
      containers:
        - name: vault
          image: vault:1.15.0
          args:
            - "server"
            - "-config=/vault/config/vault.hcl"
          ports:
            - containerPort: 8200
              name: api
            - containerPort: 8201
              name: cluster
          securityContext:
            runAsNonRoot: true
            runAsUser: 100
            capabilities:
              add:
                - IPC_LOCK
          env:
            - name: VAULT_CLUSTER_ADDR
              value: "https://127.0.0.1:8201"
            - name: VAULT_API_ADDR
              value: "https://127.0.0.1:8200"
            - name: VAULT_SKIP_VERIFY
              value: "false"
          volumeMounts:
            - name: vault-config
              mountPath: /vault/config
            - name: vault-data
              mountPath: /vault/data
            - name: vault-logs
              mountPath: /vault/logs
          livenessProbe:
            httpGet:
              path: /v1/sys/health
              port: 8200
              scheme: HTTPS
            initialDelaySeconds: 60
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /v1/sys/health
              port: 8200
              scheme: HTTPS
            initialDelaySeconds: 30
            periodSeconds: 5
      volumes:
        - name: vault-config
          configMap:
            name: vault-config
        - name: vault-logs
          emptyDir: {}
  volumeClaimTemplates:
    - metadata:
        name: vault-data
      spec:
        accessModes: [ReadWriteOnce]
        resources:
          requests:
            storage: 10Gi

---
apiVersion: v1
kind: Service
metadata:
  name: vault
  namespace: vault
spec:
  clusterIP: None
  ports:
    - port: 8200
      targetPort: 8200
      name: api
    - port: 8201
      targetPort: 8201
      name: cluster
  selector:
    app: vault

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: vault-config
  namespace: vault
data:
  vault.hcl: |
    storage "raft" {
      path    = "/vault/data"
      node_id = "node1"
    }

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

    api_addr     = "https://vault:8200"
    cluster_addr = "https://vault:8201"
    ui = true
```

### 3. **Vault Secret Configuration**

```bash
#!/bin/bash
# vault-setup.sh - Configure Vault for applications

set -euo pipefail

VAULT_ADDR="https://vault:8200"
VAULT_TOKEN="${VAULT_TOKEN}"

export VAULT_ADDR
export VAULT_TOKEN

echo "Setting up Vault secrets..."

# Enable secret engines
vault secrets enable -version=2 kv
vault secrets enable -path=database database

# Create database credentials
vault write database/config/mydb \
  plugin_name=postgresql-database-plugin \
  allowed_roles="readonly,readwrite" \
  connection_url="postgresql://{{username}}:{{password}}@postgres:5432/mydb" \
  username="vault_admin" \
  password="vault_password"

# Create database roles
vault write database/roles/readonly \
  db_name=mydb \
  creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';" \
  revocation_statements="DROP ROLE IF EXISTS \"{{name}}\";" \
  default_ttl="1h" \
  max_ttl="24h"

# Create API secrets
vault kv put secret/api/keys \
  github_token="ghp_xxxxxxxxxxx" \
  aws_access_key="AKIAIOSFODNN7EXAMPLE" \
  aws_secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \
  slack_webhook="https://hooks.slack.com/services/..."

# Create TLS certificates
vault write -f pki/root/generate/internal \
  common_name="my-root-ca" \
  ttl="87600h"

vault write pki/roles/my-domain \
  allowed_domains="*.myapp.com,myapp.com" \
  allow_subdomains=true \
  max_ttl="720h"

# Setup auto-unseal
vault write sys/seal/migrate/start \
  migrate_from_seal_type="shamir"

echo "Vault setup completed"
```

### 4. **AWS Secrets Manager Configuration**

```python
# aws-secrets-manager.py
import boto3
import json
from datetime import datetime

class SecretsManager:
    def __init__(self, region='us-east-1'):
        self.client = boto3.client('secretsmanager', region_name=region)

    def create_secret(self, name, secret_value, tags=None):
        """Create a new secret"""
        try:
            response = self.client.create_secret(
                Name=name,
                SecretString=json.dumps(secret_value),
                Tags=tags or []
            )
            return response['ARN']
        except Exception as e:
            print(f"Error creating secret: {e}")
            raise

    def get_secret(self, name):
        """Retrieve a secret"""
        try:
            response = self.client.get_secret_value(SecretId=name)
            return json.loads(response['SecretString'])
        except Exception as e:
            print(f"Error retrieving secret: {e}")
            raise

    def update_secret(self, name, secret_value):
        """Update a secret"""
        try:
            response = self.client.update_secret(
                SecretId=name,
                SecretString=json.dumps(secret_value)
            )
            return response['ARN']
        except Exception as e:
            print(f"Error updating secret: {e}")
            raise

    def rotate_secret(self, name, rotation_rules):
        """Enable automatic rotation"""
        try:
            self.client.rotate_secret(
                SecretId=name,
                RotationRules=rotation_rules
            )
        except Exception as e:
            print(f"Error rotating secret: {e}")
            raise

    def list_secrets(self):
        """List all secrets"""
        try:
            response = self.client.list_secrets()
            return response['SecretList']
        except Exception as e:
            print(f"Error listing secrets: {e}")
            raise

    def delete_secret(self, name, recovery_days=30):
        """Delete a secret with recovery window"""
        try:
            response = self.client.delete_secret(
                SecretId=name,
                RecoveryWindowInDays=recovery_days
            )
            return response
        except Exception as e:
            print(f"Error deleting secret: {e}")
            raise

# Usage
if __name__ == '__main__':
    manager = SecretsManager()

    # Create database credentials secret
    db_creds = {
        'username': 'admin',
        'password': 'SecurePassword123!',
        'host': 'postgres.example.com',
        'port': 5432,
        'dbname': 'myapp'
    }

    secret_arn = manager.create_secret(
        'prod/database/credentials',
        db_creds,
        tags=[
            {'Key': 'Environment', 'Value': 'production'},
            {'Key': 'Service', 'Value': 'myapp'}
        ]
    )

    print(f"Secret created: {secret_arn}")

    # Setup rotation
    manager.rotate_secret(
        'prod/database/credentials',
        {'AutomaticallyAfterDays': 30}
    )

    # Retrieve secret
    retrieved = manager.get_secret('prod/database/credentials')
    print(f"Retrieved secret: {retrieved}")
```

### 5. **Kubernetes Secrets**

```yaml
# kubernetes-secrets.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-credentials
  namespace: production
type: Opaque
stringData:
  database_url: "postgresql://user:pass@postgres:5432/myapp"
  api_key: "sk_live_xxxxxxxxxxxxxx"
  jwt_secret: "your-jwt-secret-key"

---
apiVersion: v1
kind: Secret
metadata:
  name: docker-registry
  namespace: production
type: kubernetes.io/dockercfg
data:
  .dockercfg: <base64-encoded-dockerconfig>

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      # Use external secrets operator
      serviceAccountName: myapp
      containers:
        - name: app
          image: myapp:latest
          env:
            # From Kubernetes secret
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: app-credentials
                  key: database_url
            # From mounted secret
            - name: API_KEY
              valueFrom:
                secretKeyRef:
                  name: app-credentials
                  key: api_key
          volumeMounts:
            - name: secrets
              mountPath: /app/secrets
              readOnly: true
      volumes:
        - name: secrets
          secret:
            secretName: app-credentials
            defaultMode: 0400

---
# External Secrets Operator
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-secret-store
  namespace: production
spec:
  provider:
    aws:
      service: SecretsManager
      region: us-east-1
      auth:
        jwt:
          serviceAccountRef:
            name: external-secrets-sa

---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: app-secrets
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secret-store
    kind: SecretStore
  target:
    name: app-external-secret
    creationPolicy: Owner
  data:
    - secretKey: database_url
      remoteRef:
        key: prod/database/url
    - secretKey: api_key
      remoteRef:
        key: prod/api/key
```

## Best Practices

### ✅ DO
- Rotate secrets regularly
- Use strong encryption
- Implement access controls
- Audit secret access
- Use managed services
- Implement secret versioning
- Encrypt secrets in transit
- Use separate secrets per environment

### ❌ DON'T
- Store secrets in code
- Use weak encryption
- Share secrets via email/chat
- Commit secrets to version control
- Use single master password
- Log secret values
- Hardcode credentials
- Disable rotation

## Resources

- [HashiCorp Vault Documentation](https://www.vaultproject.io/docs)
- [AWS Secrets Manager Documentation](https://docs.aws.amazon.com/secretsmanager/)
- [External Secrets Operator](https://external-secrets.io/)
- [Kubernetes Secrets Documentation](https://kubernetes.io/docs/concepts/configuration/secret/)

Overview

This skill implements secure secrets management patterns using HashiCorp Vault, AWS Secrets Manager, or Kubernetes Secrets to store, rotate, and audit sensitive credentials. It provides practical configuration guidance and examples to deploy centralized secret storage, enable rotation, and integrate secrets into applications across environments.

How this skill works

The skill inspects typical secret management workflows and provides implementation templates for Vault, AWS Secrets Manager, and Kubernetes Secrets. It covers initializing secret engines, creating and rotating credentials, configuring auto-unseal and PKI, and integrating external secret operators for automated sync into clusters. It also outlines operational controls like access policies, encryption, and audit logging.

When to use it

  • Storing and rotating database credentials for production services
  • Managing API keys, tokens, and service account secrets
  • Issuing and automating TLS certificate lifecycle with PKI
  • Distributing SSH keys and short-lived credentials across systems
  • Synchronizing cloud secrets into Kubernetes using external operators
  • Meeting audit and compliance requirements for access logging

Best practices

  • Rotate secrets regularly and enforce short TTLs for dynamic credentials
  • Apply least-privilege access controls and role-based policies
  • Encrypt secrets at rest and in transit; use managed KMS when possible
  • Avoid storing secrets in code or committing them to version control
  • Enable audit logging and monitor secret access patterns
  • Use separate secret stores or namespaces per environment (dev/stage/prod)

Example use cases

  • Deploy Vault in a Kubernetes StatefulSet with Raft storage and TLS for HA secret storage
  • Configure dynamic database credentials in Vault for automatic creation and revocation
  • Create and rotate application secrets in AWS Secrets Manager with automatic rotation rules
  • Mount Kubernetes Secrets into pods or sync cloud secrets via an ExternalSecrets operator
  • Issue internal TLS certificates with Vault PKI and automate renewal for services

FAQ

Which tool should I choose: Vault, AWS Secrets Manager, or Kubernetes Secrets?

Choose Vault for advanced features like dynamic secrets, PKI, and multi-cloud portability; use AWS Secrets Manager for tightly integrated managed rotation in AWS; use Kubernetes Secrets for simple in-cluster storage but pair with external providers for stronger lifecycle controls.

How often should I rotate secrets?

Rotate static secrets at least every 30–90 days and use short TTLs (minutes to hours) for dynamically generated credentials. Critical credentials may require more frequent rotation based on risk and compliance needs.