# Encryption Failures Debugging encryption errors when creating sealed secrets. ## Table of Contents - [Understanding the Encryption Flow](#understanding-the-encryption-flow) - [Certificate Problems](#certificate-problems) - [Value Issues](#value-issues) - [Scope Problems](#scope-problems) - [Browser Issues](#browser-issues) - [Network Issues](#network-issues) --- ## Understanding the Encryption Flow Before troubleshooting, understand how encryption works: ``` 1. Plugin fetches public certificate from controller GET /api/v1/namespaces/kube-system/services/sealed-secrets-controller:http/proxy/v1/cert.pem 2. Plugin validates certificate (PEM format, expiry, fingerprint) 3. Plugin encrypts value client-side using RSA-OAEP - Generates random AES-256 key - Encrypts value with AES-256-GCM - Encrypts AES key with RSA public key - Combines into encrypted payload 4. Plugin creates SealedSecret with encrypted data POST /apis/bitnami.com/v1alpha1/namespaces//sealedsecrets 5. Controller unseals secret server-side ``` **Key Points**: - Encryption happens **in browser** (plaintext never leaves your machine) - Certificate must be **valid PEM format** and **not expired** - Maximum value size: **~1MB** (RSA limitation) --- ## Certificate Problems ### "Failed to fetch certificate" #### Symptom ``` Failed to fetch certificate: Network error ``` #### Diagnosis ```bash # 1. Check controller is running kubectl get pods -n kube-system -l name=sealed-secrets-controller # 2. Test certificate endpoint directly kubectl port-forward -n kube-system service/sealed-secrets-controller 8080:8080 # In another terminal: curl http://localhost:8080/v1/cert.pem ``` #### Solutions **Controller not running**: See [Controller Issues](controller-issues.md) **Certificate endpoint not responding**: ```bash # Check controller logs kubectl logs -n kube-system -l name=sealed-secrets-controller --tail=50 # Restart controller kubectl rollout restart deployment -n kube-system sealed-secrets-controller ``` **RBAC permission denied**: ```bash # Check service access permission kubectl auth can-i get services/sealed-secrets-controller -n kube-system # If no, apply RBAC (requires cluster-admin): kubectl apply -f - < cert.pem # Should start with: # -----BEGIN CERTIFICATE----- # Should end with: # -----END CERTIFICATE----- cat cert.pem ``` #### Solutions **Corrupted certificate**: ```bash # Regenerate certificate kubectl delete secret -n kube-system sealed-secrets-key kubectl rollout restart deployment -n kube-system sealed-secrets-controller ``` **Wrong secret**: Ensure you're using correct secret: ```bash # List all sealing keys kubectl get secrets -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key # Should show sealed-secrets-key ``` --- ### "Certificate expiring soon" Warning #### Symptom ``` ⚠️ Warning: Certificate expires in 15 days ``` This is an **advance warning**, not an error. Plugin warns 30 days before expiry. #### Action Plan key rotation before expiry: 1. **Schedule maintenance window** 2. **Backup existing keys**: ```bash kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml > sealing-keys-backup.yaml ``` 3. **Rotate keys**: See [Secret Rotation Tutorial](../tutorials/secret-rotation.md) 4. **Recreate SealedSecrets** if needed --- ## Value Issues ### "Value too large" #### Symptom ``` Encryption failed: Value exceeds maximum size (1MB) ``` #### Cause RSA encryption has size limit (~1MB for RSA-2048). #### Solutions **Split into multiple secrets**: ```yaml # Instead of: apiVersion: v1 kind: Secret metadata: name: large-config data: config.json: <2MB base64 data> ❌ # Use: --- apiVersion: v1 kind: Secret metadata: name: config-part1 data: config-part1.json: <500KB base64 data> ✅ --- apiVersion: v1 kind: Secret metadata: name: config-part2 data: config-part2.json: <500KB base64 data> ✅ ``` **Use external secret management** for very large files: - HashiCorp Vault - AWS Secrets Manager - Azure Key Vault - GCP Secret Manager Then store only references in SealedSecrets: ```yaml apiVersion: v1 kind: Secret metadata: name: external-ref stringData: vault-path: "secret/data/myapp/large-config" ``` **Compress data** before encrypting: ```bash # Compress config file gzip -c config.json | base64 # Then use compressed value in plugin ``` --- ### "Empty value" #### Symptom ``` Validation failed: Secret value cannot be empty ``` #### Cause Trying to create secret with empty value. #### Solutions **Provide a value**: ```yaml stringData: password: "mysecretvalue" ✅ ``` **Use placeholder** if value unknown: ```yaml stringData: password: "changeme" # Replace later ``` **Remove key** if not needed: Don't create keys with empty values. --- ### "Invalid characters" #### Symptom ``` Encryption failed: Value contains invalid characters ``` This error is **rare** (plugin accepts any binary data). If you see it: #### Solutions **Base64-encode first** (for binary data): ```bash # Encode binary file base64 < binary-file.bin # Use in plugin with base64-encoded value ``` **Check for null bytes** in text: ```bash # Remove null bytes tr -d '\0' < file.txt ``` --- ## Scope Problems ### "Scope validation failed" #### Symptom ``` Validation failed: Invalid scope for namespace-scoped secret ``` #### Cause Scope mismatch between plugin setting and cluster policy. #### Understanding Scopes | Scope | Can Rename? | Can Move Namespace? | Use Case | |-------|------------|---------------------|----------| | `strict` | ❌ No | ❌ No | Production secrets | | `namespace-wide` | ✅ Yes | ❌ No | Dev environments | | `cluster-wide` | ✅ Yes | ✅ Yes | Shared configs | #### Solution **Use strict scope** (most secure): ```yaml # In plugin: Scope: strict Name: my-secret Namespace: production ``` **Match cluster policy**: If cluster enforces specific scope, use that: ```bash # Check cluster policy kubectl get sealedsecrets.bitnami.com -o yaml | grep -A 5 scope ``` --- ### "Scope annotation missing" #### Symptom SealedSecret created but controller doesn't unseal it. #### Diagnosis ```bash # Check SealedSecret kubectl get sealedsecret my-secret -n default -o yaml # Look for annotation: metadata: annotations: sealedsecrets.bitnami.com/scope: strict ← Should be present ``` #### Solution Plugin automatically adds scope annotation. If missing: 1. **Delete SealedSecret**: ```bash kubectl delete sealedsecret my-secret -n default ``` 2. **Recreate with plugin** (don't create manually) --- ## Browser Issues ### "Crypto API not available" #### Symptom ``` Encryption failed: Web Crypto API not available ``` #### Cause Browser doesn't support Web Crypto API (very old browser). #### Solution **Upgrade browser**: - Chrome 37+ - Firefox 34+ - Safari 11+ - Edge 79+ **Use HTTPS**: Web Crypto requires HTTPS (or localhost): ```bash # If using custom Headlamp deployment, enable HTTPS ``` --- ### "Encryption timeout" #### Symptom ``` Encryption failed: Operation timeout after 30000ms ``` #### Cause Browser crypto operation taking too long (rare). #### Solutions **Reduce value size**: If encrypting large value, split it. **Close other tabs**: Free up browser resources. **Try different browser**: Some browsers have better crypto performance. **Check browser console** for JavaScript errors: 1. View → Toggle Developer Tools 2. Console tab 3. Look for errors during encryption --- ## Network Issues ### "Certificate fetch timeout" #### Symptom ``` Failed to fetch certificate: Request timeout after 30000ms ``` #### Diagnosis ```bash # Test cluster connectivity kubectl cluster-info # Test service endpoint kubectl get svc -n kube-system sealed-secrets-controller # Test with curl kubectl port-forward -n kube-system service/sealed-secrets-controller 8080:8080 curl -m 5 http://localhost:8080/v1/cert.pem ``` #### Solutions **Slow network**: Increase timeout in plugin settings: - Settings → Sealed Secrets → Network Timeout: 60s **VPN disconnected**: Reconnect VPN if using one. **Firewall blocking**: Check firewall allows Kubernetes API access. --- ### "CORS error" #### Symptom (Browser Console) ``` Access blocked by CORS policy ``` #### Cause Cross-origin request blocked (should not happen in normal usage). #### Solution **Use Headlamp's built-in proxy** (enabled by default). If developing plugin locally: ```bash # Start Headlamp in dev mode npm start # Headlamp automatically proxies requests ``` --- ## Debugging Encryption ### Enable Debug Logging In browser console: ```javascript // Enable debug logs localStorage.setItem('debug', 'headlamp-sealed-secrets:*') // Reload page location.reload() // Try encryption again // Check console for detailed logs ``` ### Manual Encryption Test Test encryption manually: ```javascript // In browser console const cert = await fetch('/api/v1/namespaces/kube-system/services/sealed-secrets-controller:http/proxy/v1/cert.pem') .then(r => r.text()); console.log('Certificate:', cert); // Should show PEM certificate starting with: // -----BEGIN CERTIFICATE----- ``` ### Verify Encrypted Output ```bash # After creating SealedSecret, verify it kubectl get sealedsecret my-secret -n default -o yaml # Should show: # spec: # encryptedData: # password: AgB... (base64 encrypted value) ``` --- ## Advanced Debugging ### Test with kubeseal CLI If plugin fails but kubeseal works, it's a plugin issue: ```bash # Install kubeseal wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/kubeseal-0.24.0-linux-amd64.tar.gz tar -xzf kubeseal-0.24.0-linux-amd64.tar.gz sudo install -m 755 kubeseal /usr/local/bin/kubeseal # Test encryption echo -n mysecretvalue | kubeseal \ --controller-namespace=kube-system \ --controller-name=sealed-secrets-controller \ --format=yaml \ --name=my-secret \ --namespace=default \ --scope=strict # If this works, plugin has a bug # If this fails too, controller/cluster issue ``` ### Compare Encryption ```bash # Encrypt same value with both methods # Plugin output: kubectl get sealedsecret my-secret-plugin -n default -o jsonpath='{.spec.encryptedData.password}' # kubeseal output: echo -n mysecretvalue | kubeseal --raw --cert cert.pem --scope strict --name my-secret --namespace default # Values should be different (encryption is random) # But both should unseal to same plaintext ``` --- ## Getting Help If encryption still fails: 1. **Gather diagnostics**: ```bash # Controller version kubectl get deployment -n kube-system sealed-secrets-controller -o jsonpath='{.spec.template.spec.containers[0].image}' # Certificate validity kubectl get secret -n kube-system sealed-secrets-key -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -text # Plugin version (in Headlamp UI) Settings → Sealed Secrets → About ``` 2. **Enable debug logging** (see above) 3. **Try kubeseal CLI** to isolate issue 4. **Report issue**: - [Plugin Issues](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/issues) - [Controller Issues](https://github.com/bitnami-labs/sealed-secrets/issues) Include: - Browser and version - Plugin version - Controller version - Full error message - Browser console logs - Steps to reproduce ## See Also - [Common Errors](common-errors.md) - General troubleshooting - [Controller Issues](controller-issues.md) - Controller-specific problems - [Encryption Flow](../architecture/encryption-flow.md) - How encryption works - [Creating Secrets](../user-guide/creating-secrets.md) - Usage guide