Files
juwan-backend/docs/secrets
wwweww fdbcde13b2 add:
2026-02-23 20:36:21 +08:00
..
2026-02-23 20:36:21 +08:00
2026-02-23 20:36:21 +08:00
2026-02-23 20:36:21 +08:00
2026-02-23 20:36:21 +08:00
2026-02-23 20:36:21 +08:00
2026-02-23 20:36:21 +08:00
2026-02-23 20:36:21 +08:00
2026-02-23 20:36:21 +08:00
2026-02-23 20:36:21 +08:00

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

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:
spec:
  template:
    spec:
      serviceAccountName: user-rpc
  1. 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:

  1. Set the serviceAccountName:
spec:
  template:
    spec:
      serviceAccountName: envoy-gateway
  1. 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-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:
    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:

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