Create comprehensive tutorials and user guides for common workflows and core concepts. New tutorials: - tutorials/ci-cd-integration.md (8KB) - Complete CI/CD guide - GitHub Actions, GitLab CI, and Jenkins examples - Certificate management and kubeseal CLI usage - Bulk secret creation and environment-specific patterns - Troubleshooting and best practices New user guides: - user-guide/scopes-explained.md (12KB) - Deep dive into scopes - Detailed explanation of strict/namespace-wide/cluster-wide - Security implications and use cases - Decision tree for scope selection - Common mistakes and how to avoid them - Scope comparison table - user-guide/rbac-permissions.md (10KB) - RBAC configuration - Required permissions for different access levels - Example RBAC configurations (viewer, creator, admin) - Service account setup for CI/CD - Plugin UI behavior based on permissions - Troubleshooting permission issues - Security best practices Benefits: - Real-world examples for GitHub Actions, GitLab CI, Jenkins - Clear security guidance with decision trees - Copy-paste RBAC manifests for common scenarios - Troubleshooting sections for each guide - Cross-referenced with other documentation Phase 3 deliverables (3-4 days estimated, completed in 1 session): ✅ CI/CD integration tutorial with 3 platform examples ✅ Scopes explained with security best practices ✅ RBAC permissions guide with example manifests ✅ Decision trees and comparison tables ✅ Troubleshooting sections for each guide Total documentation: - 30KB of new tutorial/guide content - 3 comprehensive guides - 20+ code examples - Cross-referenced with API docs and other guides Next: Phase 4 - Troubleshooting guides and ADRs Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
10 KiB
Scopes Explained
Understanding SealedSecret scopes and when to use each one.
What are Scopes?
Scopes determine where a SealedSecret can be unsealed. They control the binding between the encrypted data and its Kubernetes resource identity (namespace and/or name).
Think of scopes as security levels for your encrypted secrets:
- Strict = Locked to specific name + namespace (most secure)
- Namespace-wide = Locked to namespace (can rename)
- Cluster-wide = Can move anywhere (least secure)
The Three Scopes
Strict Scope (Recommended)
Binding: Namespace + Name + Key
The sealed secret can ONLY be unsealed if all three match:
- ✅ Same namespace
- ✅ Same secret name
- ✅ Same key name
Example:
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: db-credentials
namespace: production
spec:
encryptedData:
password: AgB... # Can ONLY be unsealed as:
# - name: db-credentials
# - namespace: production
# - key: password
Use when:
- Production secrets
- Database credentials
- API keys
- Any sensitive data
Advantages:
- ✅ Maximum security
- ✅ Prevents accidental leaks from renaming
- ✅ Prevents cross-namespace access
Limitations:
- ❌ Cannot rename the secret
- ❌ Cannot move to different namespace
- ❌ Must re-encrypt if name/namespace changes
Creating with Headlamp:
- Click "Create Sealed Secret"
- Select "strict" scope (default)
- Fill in name, namespace, and secret data
- Click "Create"
Creating with kubeseal:
kubectl create secret generic db-credentials \
--namespace production \
--from-literal=password=mysecret \
--dry-run=client -o yaml | \
kubeseal --cert cert.pem --scope strict --format yaml
Namespace-Wide Scope
Binding: Namespace + Key
The sealed secret can be unsealed if:
- ✅ Same namespace
- ✅ Same key name
- ⚠️ Any secret name (can rename)
Example:
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: app-config
namespace: staging
spec:
encryptedData:
api-url: AgB... # Can be unsealed as:
# - name: app-config (or ANY name)
# - namespace: staging (must match)
# - key: api-url (must match)
Use when:
- Shared configuration across multiple apps in a namespace
- Secrets that might be renamed
- Non-critical secrets
Advantages:
- ✅ Flexible naming
- ✅ Can rename secret without re-encryption
- ✅ Still namespace-isolated
Limitations:
- ❌ Less secure than strict
- ❌ Cannot move to different namespace
- ❌ Anyone in namespace can unseal by creating correctly-named secret
Creating with Headlamp:
- Click "Create Sealed Secret"
- Select "namespace-wide" scope
- Fill in namespace and secret data
- Name can be changed later
Creating with kubeseal:
kubectl create secret generic temp-name \
--namespace staging \
--from-literal=api-url=https://api.staging.example.com \
--dry-run=client -o yaml | \
kubeseal --cert cert.pem --scope namespace-wide --format yaml
Cluster-Wide Scope
Binding: Key only
The sealed secret can be unsealed if:
- ⚠️ Any namespace
- ⚠️ Any secret name
- ✅ Same key name
Example:
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: global-config
namespace: default
spec:
encryptedData:
license-key: AgB... # Can be unsealed as:
# - name: ANY
# - namespace: ANY
# - key: license-key (must match)
Use when:
- Truly global configuration
- License keys used across all namespaces
- Public URLs or non-sensitive config
Advantages:
- ✅ Maximum flexibility
- ✅ Can move anywhere in cluster
- ✅ Can rename freely
Limitations:
- ❌ Least secure
- ❌ Anyone in cluster can unseal
- ❌ Easy to accidentally expose
Creating with Headlamp:
- Click "Create Sealed Secret"
- Select "cluster-wide" scope
- Fill in secret data
- Can deploy to any namespace
Creating with kubeseal:
kubectl create secret generic temp \
--from-literal=license-key=ABC123 \
--dry-run=client -o yaml | \
kubeseal --cert cert.pem --scope cluster-wide --format yaml
Scope Comparison
| Feature | Strict | Namespace-Wide | Cluster-Wide |
|---|---|---|---|
| Security | 🔒🔒🔒 High | 🔒🔒 Medium | 🔒 Low |
| Can rename | ❌ No | ✅ Yes | ✅ Yes |
| Can move namespace | ❌ No | ❌ No | ✅ Yes |
| Binding | Name+NS+Key | NS+Key | Key only |
| Use case | Production secrets | Shared namespace config | Global config |
| Recommended for | Credentials, API keys | App config | Public URLs |
Decision Tree
┌─────────────────────────────────┐
│ Is this a sensitive credential? │
│ (password, API key, token, etc) │
└─────────┬──────────────┬────────┘
│ │
YES NO
│ │
v v
┌─────────┐ ┌──────────────────┐
│ strict │ │ Could this value │
│ scope │ │ be shared across │
└─────────┘ │ your cluster? │
└────┬────────┬────┘
│ │
YES NO
│ │
v v
┌──────────┐ ┌──────────────┐
│cluster- │ │namespace- │
│wide scope│ │wide scope │
└──────────┘ └──────────────┘
Examples by Use Case
Database Credentials (Strict)
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: postgres-credentials
namespace: production
spec:
encryptedData:
username: AgB...
password: AgB...
host: AgB...
Why strict? Credentials must not leak to other namespaces or be accessible via renaming.
Application Config (Namespace-Wide)
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: app-config
namespace: staging
spec:
encryptedData:
api-url: AgB...
timeout: AgB...
log-level: AgB...
Why namespace-wide? Config is specific to staging but might be used by multiple apps (with different names).
License Key (Cluster-Wide)
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: company-license
namespace: default
spec:
encryptedData:
license-key: AgB...
Why cluster-wide? The same license applies to all namespaces and environments.
Changing Scopes
You cannot change a scope after encryption. To change scope:
-
Delete the old sealed secret:
kubectl delete sealedsecret old-secret -n production -
Re-encrypt with new scope:
kubectl create secret generic old-secret \ --namespace production \ --from-literal=password=value \ --dry-run=client -o yaml | \ kubeseal --cert cert.pem --scope namespace-wide --format yaml > new-sealed-secret.yaml -
Apply new sealed secret:
kubectl apply -f new-sealed-secret.yaml
Security Best Practices
1. Default to Strict
Always use strict scope unless you have a specific reason not to:
✅ Good:
# Explicit strict scope
kubeseal --scope strict
❌ Risky:
# Using cluster-wide for credentials
kubeseal --scope cluster-wide # Don't do this for secrets!
2. Audit Your Scopes
List all sealed secrets and their scopes:
kubectl get sealedsecrets --all-namespaces -o json | \
jq -r '.items[] | "\(.metadata.namespace)/\(.metadata.name): \(.spec.template.type // "strict")"'
3. Separate Sensitive from Non-Sensitive
# Sensitive → strict
kubectl create secret generic db-creds --from-literal=password=... | \
kubeseal --scope strict
# Non-sensitive → namespace-wide or cluster-wide
kubectl create secret generic app-urls --from-literal=api=https://... | \
kubeseal --scope namespace-wide
4. Document Scope Choices
Add annotations to explain why a scope was chosen:
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: db-credentials
namespace: production
annotations:
sealedsecrets.scope: "strict"
sealedsecrets.reason: "Database credentials must not be accessible outside production namespace"
spec:
encryptedData:
password: AgB...
Common Mistakes
❌ Using Cluster-Wide for Everything
# DON'T: Encrypting passwords with cluster-wide scope
kubeseal --scope cluster-wide < secret-with-passwords.yaml
Problem: Anyone in any namespace can create a secret with the same key name and unseal it.
Solution: Use strict scope for credentials.
❌ Renaming Strict-Scoped Secrets
# Create strict-scoped secret
kubectl apply -f db-secret.yaml # name: db-credentials
# Later, try to rename
kubectl apply -f db-secret.yaml # name: database-creds (DIFFERENT NAME)
Problem: Sealed secret won't unseal because name changed.
Solution: Re-encrypt with new name or use namespace-wide scope.
❌ Moving Secrets Between Namespaces
# Seal for production
kubectl create secret generic app-secret --namespace production | kubeseal
# Try to use in staging
kubectl apply -f sealed-secret.yaml --namespace staging
Problem: Won't unseal (namespace mismatch with strict or namespace-wide scope).
Solution: Re-encrypt for the target namespace or use cluster-wide (if appropriate).
Next Steps
- RBAC Permissions - Control who can create/view sealed secrets
- Creating Secrets - Complete guide to secret creation
- Secret Rotation - Rotate secrets and keys