149 lines
3.5 KiB
Markdown
149 lines
3.5 KiB
Markdown
# 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
|
|
```
|