# JWT Secret Management This directory contains secure configuration for JWT secret key management. ## Files - `jwt-secret.yaml`: Kubernetes Secret + ServiceAccount + RBAC rules - `ENCRYPTION.md`: Guide for enabling ETCD static encryption at rest ## Quick Start ### 1. Create the Secret and RBAC ```bash kubectl apply -f deploy/k8s/secrets/jwt-secret.yaml ``` This will create: - Secret `jwt-secret` in namespace `juwan` containing the JWT secret key - ServiceAccount `user-rpc` in namespace `juwan` - ServiceAccount `envoy-gateway` in namespace `juwan` - Role `jwt-secret-reader` that allows reading only `jwt-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: 1. Set the serviceAccountName: ```yaml spec: template: spec: serviceAccountName: user-rpc ``` 2. Add environment variable to load JWT secret: ```yaml 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: 1. Set the serviceAccountName: ```yaml spec: template: spec: serviceAccountName: envoy-gateway ``` 2. Add environment variable or mount Secret: ```yaml 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: ```yaml 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-rpc` and `envoy-gateway` can 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: 1. Generate a new key 2. Update the Secret: ```bash kubectl create secret generic jwt-secret --from-literal=secret-key=NEW_KEY --dry-run=client -o yaml | kubectl apply -f - ``` 3. Pod mounts/env vars will be updated automatically within a few minutes 4. 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: ```bash kubectl get deployment user-rpc -o yaml | grep serviceAccountName ``` ### Secret not being mounted Verify the Secret exists: ```bash kubectl get secret jwt-secret -n juwan ``` Check Pod logs for mounting errors: ```bash kubectl logs -l app=user-rpc -n juwan ``` ### Permission denied error Verify RBAC binding: ```bash kubectl get rolebinding -n juwan kubectl get role jwt-secret-reader -n juwan ```