282025ca24
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>
397 lines
10 KiB
Markdown
397 lines
10 KiB
Markdown
# 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:**
|
|
```yaml
|
|
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:**
|
|
1. Click "Create Sealed Secret"
|
|
2. Select **"strict"** scope (default)
|
|
3. Fill in name, namespace, and secret data
|
|
4. Click "Create"
|
|
|
|
**Creating with kubeseal:**
|
|
```bash
|
|
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:**
|
|
```yaml
|
|
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:**
|
|
1. Click "Create Sealed Secret"
|
|
2. Select **"namespace-wide"** scope
|
|
3. Fill in namespace and secret data
|
|
4. Name can be changed later
|
|
|
|
**Creating with kubeseal:**
|
|
```bash
|
|
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:**
|
|
```yaml
|
|
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:**
|
|
1. Click "Create Sealed Secret"
|
|
2. Select **"cluster-wide"** scope
|
|
3. Fill in secret data
|
|
4. Can deploy to any namespace
|
|
|
|
**Creating with kubeseal:**
|
|
```bash
|
|
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)
|
|
|
|
```yaml
|
|
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)
|
|
|
|
```yaml
|
|
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)
|
|
|
|
```yaml
|
|
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:
|
|
|
|
1. **Delete the old sealed secret**:
|
|
```bash
|
|
kubectl delete sealedsecret old-secret -n production
|
|
```
|
|
|
|
2. **Re-encrypt with new scope**:
|
|
```bash
|
|
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
|
|
```
|
|
|
|
3. **Apply new sealed secret**:
|
|
```bash
|
|
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:**
|
|
```bash
|
|
# Explicit strict scope
|
|
kubeseal --scope strict
|
|
```
|
|
|
|
❌ **Risky:**
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
kubectl get sealedsecrets --all-namespaces -o json | \
|
|
jq -r '.items[] | "\(.metadata.namespace)/\(.metadata.name): \(.spec.template.type // "strict")"'
|
|
```
|
|
|
|
### 3. Separate Sensitive from Non-Sensitive
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```yaml
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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](rbac-permissions.md)** - Control who can create/view sealed secrets
|
|
- **[Creating Secrets](creating-secrets.md)** - Complete guide to secret creation
|
|
- **[Secret Rotation](../tutorials/secret-rotation.md)** - Rotate secrets and keys
|
|
|
|
## Resources
|
|
|
|
- [Sealed Secrets Scopes Documentation](https://github.com/bitnami-labs/sealed-secrets#scopes)
|
|
- [Security Best Practices](../deployment/security-hardening.md)
|