Stage 5 · Platform
Configuration & Secrets Management
Secret Leak Prevention
kubeseal, SOPS, Sealed Secrets, RBAC scoping, and audit log safeguards.
Secret Leak Risks
Secret leaks happen through: committing secrets to Git, exposing secrets in logs, granting excessive RBAC permissions, and sharing secrets in Slack/email. Preventing leaks requires multiple layers: encryption, access control, scanning, and monitoring.
- Never commit secrets to Git repositories
- Use Sealed Secrets or SOPS for encrypted secret storage
- Enable git secret scanning (GitHub, GitLab, GitLeaks)
- Scope RBAC to limit secret access
- Enable audit logging for secret access
- Use External Secrets to avoid storing in etcd
Sealed Secrets
Sealed Secrets encrypt secrets so they can be safely committed to Git. The SealedSecret is encrypted with the cluster's public key. Only the controller running in the cluster can decrypt it. This enables GitOps for secrets.
# Create a regular Secret
kubectl create secret generic db-credentials \
--from-literal=password=mypassword \
-n production --dry-run=client -o yaml > secret.yaml
# Seal it (encrypted, safe for Git)
kubeseal --format yaml < secret.yaml > sealed-secret.yaml
# sealed-secret.yaml is safe to commit to Git
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: db-credentials
namespace: production
spec:
encryptedData:
password: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq...
---
# Apply to cluster — controller decrypts to regular Secret
kubectl apply -f sealed-secret.yamlkubeseal encrypts secrets using the controller's public key. The encrypted Secret is safe to commit to Git. When applied, the controller decrypts it and creates a regular Secret. The private key never leaves the cluster.
SOPS Encryption
SOPS (Secrets OPerationS) encrypts secrets in YAML, JSON, or ENV files. It supports multiple key providers: AWS KMS, Azure Key Vault, GCP KMS, and PGP. SOPS encrypts values but keeps keys visible for readability.
# Before encryption (plain)
db_password: mypassword
api_key: sk-1234567890
---
# After encryption with SOPS
db_password: ENC[AES256_GCM,data:encrypted...]
api_key: ENC[AES256_GCM,data:encrypted...]
sops:
kms:
- arn: "arn:aws:kms:us-east-1:123456789:key/12345678-..."
created_at: "2024-01-15T10:00:00Z"
enc: "..."
lastmodified: "2024-01-15T10:00:00Z"
version: 3.8.1
---
# Encrypt a file
sops --encrypt --kms "arn:aws:kms:..." secret.yaml > secret.enc.yaml
# Decrypt a file
sops --decrypt secret.enc.yaml > secret.yaml
# Edit encrypted file in place
sops secret.enc.yamlSOPS encrypts values but preserves YAML structure. You can see which keys exist without seeing their values. Git diff shows which keys changed. SOPS is ideal for GitOps — encrypted secrets in Git, decrypted at deploy time.
Git Secret Scanning
Secret scanning tools detect secrets committed to Git repositories. GitHub and GitLab have built-in scanning. Third-party tools (GitLeaks, TruffleHog, detect-secrets) provide pre-commit hooks and CI/CD integration.
# Install GitLeaks
brew install gitleaks
# Scan repository
gitleaks detect --source . --verbose
# Pre-commit hook
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
---
# CI/CD integration
# .github/workflows/secret-scan.yml
name: Secret Scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}GitLeaks scans for patterns: AWS keys, API tokens, passwords, private keys. Pre-commit hooks catch secrets before they enter Git. CI/CD scanning catches secrets in pull requests. Both are recommended.
RBAC Scoping
Limit who can read secrets using RBAC. Most workloads don't need secret access. Use dedicated service accounts with minimal permissions. Restrict secret access to specific namespaces and resources.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
namespace: production
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
resourceNames: ["app-config", "db-credentials"] # Only specific secrets
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: secret-reader-binding
namespace: production
subjects:
- kind: ServiceAccount
name: app-reader
roleRef:
kind: Role
name: secret-reader
apiGroup: rbac.authorization.k8s.ioresourceNames restricts access to specific secrets. Without resourceNames, the SA can read all secrets in the namespace. Always list specific secrets rather than granting blanket access.
Audit Log Safeguards
Audit logs record who accessed what and when. Enable audit logging for secret access. Monitor for unusual patterns: bulk secret reads, access from unexpected namespaces, or access outside business hours.
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
resources:
- group: ""
resources: ["secrets"]
verbs: ["get", "list", "watch"]
# Log all secret access with request and response
- level: Metadata
resources:
- group: ""
resources: ["secrets"]
verbs: ["create", "update", "patch", "delete"]
# Log metadata for secret modificationsRequestResponse level logs the full request and response body. Metadata level logs only the metadata (who, when, what). Use RequestResponse for secret reads to track exactly which secrets were accessed.
If a secret is leaked: 1) Rotate the secret immediately in the source system, 2) Update the Kubernetes Secret, 3) Restart affected pods, 4) Audit logs to determine scope, 5) Add preventive controls to prevent recurrence.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.