🎓 LEVEL 37 DEBRIEF: Base64 Encoding ≠ Encryption¶
Congratulations! You've discovered a critical security lesson about Kubernetes Secrets!
The Critical Lesson: Base64 is NOT Security¶
What You Saw:
data:
username: YWRtaW4= # Looks encrypted... but it's not!
password: c2VjcmV0cGFzczEyMw== # Anyone can decode this!
What Actually Happens:
# Anyone with kubectl access can decode instantly:
$ kubectl get secret db-credentials -n k8squest -o jsonpath='{.data.username}' | base64 -d
admin
$ kubectl get secret db-credentials -n k8squest -o jsonpath='{.data.password}' | base64 -d
secretpass123
Result: Zero security - base64 is just encoding, not encryption!
🔍 Understanding the Difference¶
Base64 Encoding (What Kubernetes Uses)¶
Purpose: Convert binary data to text format
Characteristics: - ✅ Handles binary data (certs, keys) - ✅ Avoids YAML special characters - ❌ Provides ZERO security - ❌ Trivially reversible (no key needed) - ❌ Anyone with kubectl access can decode
Example:
echo -n "admin" | base64 # Encode: YWRtaW4=
echo "YWRtaW4=" | base64 -d # Decode: admin (no key needed!)
Encryption (What You Actually Need)¶
Purpose: Hide data from unauthorized access
Characteristics: - ✅ Requires a secret key to decrypt - ✅ Cannot be reversed without the key - ✅ Actually provides security - ✅ Protects against unauthorized access
Example:
# With AES encryption (requires key!)
echo "admin" | openssl enc -aes-256-cbc -k "secret-key" -base64
# Can only decrypt with the correct key
Method 2: Kubernetes Auto-Encoding (stringData)
apiVersion: v1
kind: Secret
metadata:
name: db-creds
type: Opaque
stringData: # ✅ Kubernetes encodes for you!
username: admin # Plain text OK here
password: secret # Plain text OK here
Encoding Commands¶
# Encode
echo -n "admin" | base64
# YWRtaW4=
# Decode
echo "YWRtaW4=" | base64 -d
# admin
# IMPORTANT: Use -n to avoid encoding newline!
echo "admin" | base64 # ❌ Includes newline
echo -n "admin" | base64 # ✅ Correct
💥 Common Mistakes¶
Mistake 1: Forgetting -n Flag¶
echo "password" | base64
# cGFzc3dvcmQK # ❌ Has extra newline encoded!
echo -n "password" | base64
# cGFzc3dvcmQ= # ✅ Correct
Mistake 2: Double Encoding¶
# First encoding
ENCODED=$(echo -n "secret" | base64)
# Second encoding (wrong!)
echo $ENCODED | base64 # ❌ Encoded twice!
Mistake 3: Plain Text in data Field¶
data:
password: mysecret # ❌ Should be base64!
# The API rejects values that are not valid base64.
# Use stringData for unencoded text input instead.
🛡️ Best Practices¶
-
Use stringData for simplicity:
-
Use kubectl create secret:
-
Validate encoding:
-
Never commit decoded secrets:
🔐 Real Secret Security Solutions¶
Since base64 provides no security, here's what you should actually use:
1. Encryption at Rest (etcd encryption)¶
# /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-byte-key>
- identity: {}
2. Sealed Secrets (Bitnami)¶
# Encrypt secret that can only be decrypted in-cluster
kubeseal --format=yaml < secret.yaml > sealed-secret.yaml
# Safe to commit sealed-secret.yaml to git!
3. External Secrets Operator¶
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-creds
spec:
secretStoreRef:
name: aws-secrets-manager
target:
name: db-credentials
data:
- secretKey: password
remoteRef:
key: prod/db/password
4. HashiCorp Vault¶
# Inject secrets directly into pods
vault kv put secret/db username=admin password=secret
# Pods use Vault Agent Injector
5. RBAC (Role-Based Access Control)¶
# Restrict who can read secrets
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
resourceNames: ["specific-secret"] # Limit to specific secrets
🎯 Key Takeaways¶
- Base64 is encoding, NOT encryption - Provides zero security
- Anyone with kubectl access can decode secrets - RBAC is critical
- Secrets in etcd are just base64 by default - Enable encryption at rest
- Use external secret managers - Vault, Sealed Secrets, ESO
- Defense in depth - RBAC + encryption at rest + external secrets
- Never commit decoded secrets to git - Use Sealed Secrets or ESO
Well done! You understand why Kubernetes Secrets need additional security layers! 🎉