3.7 KiB
3.7 KiB
JWT Secret Management
This directory contains secure configuration for JWT secret key management.
Files
jwt-secret.yaml: Kubernetes Secret + ServiceAccount + RBAC rulesENCRYPTION.md: Guide for enabling ETCD static encryption at rest
Quick Start
1. Create the Secret and RBAC
kubectl apply -f deploy/k8s/secrets/jwt-secret.yaml
This will create:
- Secret
jwt-secretin namespacejuwancontaining the JWT secret key - ServiceAccount
user-rpcin namespacejuwan - ServiceAccount
envoy-gatewayin namespacejuwan - Role
jwt-secret-readerthat allows reading onlyjwt-secret - RoleBindings to grant both ServiceAccounts read permission on the secret
2. Update user-rpc Deployment
Update deploy/k8s/service/user/user-rpc.yaml to:
- Set the serviceAccountName:
spec:
template:
spec:
serviceAccountName: user-rpc
- Add environment variable to load JWT secret:
spec:
template:
spec:
containers:
- name: user-rpc
env:
- name: JWT_SECRET_KEY
valueFrom:
secretKeyRef:
name: jwt-secret
key: secret-key
3. Update envoy-gateway Deployment
Update deploy/k8s/envoy/envoy.yaml to:
- Set the serviceAccountName:
spec:
template:
spec:
serviceAccountName: envoy-gateway
- Add environment variable or mount Secret:
volumeMounts:
- name: jwt-secret
mountPath: /etc/jwt
readOnly: true
volumes:
- name: jwt-secret
secret:
secretName: jwt-secret
defaultMode: 0400
Then reference it in the Envoy config:
data:
envoy.yaml: |
# Read JWT secret from /etc/jwt/secret-key
4. Enable ETCD Encryption
Follow the guide in ENCRYPTION.md to enable static encryption at rest for all secrets in ETCD.
Security Considerations
Least Privilege
- Only
user-rpcandenvoy-gatewaycan read the JWT secret - No other services or users have access
- The Role allows reading only the
jwt-secret, not other secrets
Encryption at Rest
- With ETCD encryption enabled, the secret is encrypted when stored on disk
- Even if someone gains access to the ETCD database files, they cannot read the secret without the encryption key
Secret Rotation
To rotate the JWT secret key:
- Generate a new key
- Update the Secret:
kubectl create secret generic jwt-secret --from-literal=secret-key=NEW_KEY --dry-run=client -o yaml | kubectl apply -f - - Pod mounts/env vars will be updated automatically within a few minutes
- Old tokens will become invalid (you may need to log users out)
Production Checklist
- ETCD encryption enabled (see ENCRYPTION.md)
- JWT secret key changed from default
- Both user-rpc and envoy-gateway Deployments use correct serviceAccountName
- Both Deployments load the secret via environment variable or volume mount
- Regular secret rotation policy implemented
- Secret backup stored in secure location (encrypted)
- RBAC audit logging enabled to track secret access
Troubleshooting
Cannot read jwt-secret
Check if the Pod is using the correct ServiceAccount:
kubectl get deployment user-rpc -o yaml | grep serviceAccountName
Secret not being mounted
Verify the Secret exists:
kubectl get secret jwt-secret -n juwan
Check Pod logs for mounting errors:
kubectl logs -l app=user-rpc -n juwan
Permission denied error
Verify RBAC binding:
kubectl get rolebinding -n juwan
kubectl get role jwt-secret-reader -n juwan