# JWT + ETCD 加密系统 - 快速参考卡片

## 一页速查表

### 部署命令

```bash
# 创建 Secret 和 RBAC
kubectl apply -f deploy/k8s/secrets/jwt-secret.yaml

# 更新 Deployments
kubectl apply -f deploy/k8s/service/user/user-rpc.yaml
kubectl apply -f deploy/k8s/envoy/envoy.yaml

# 验证部署
kubectl get secret jwt-secret -n juwan
kubectl get sa user-rpc envoy-gateway -n juwan
kubectl get role jwt-secret-reader -n juwan
kubectl get pods -n juwan -l app=user-rpc
kubectl get pods -n juwan -l app=envoy-gateway
```

### 权限验证

```bash
# user-rpc 可以读 jwt-secret
kubectl auth can-i get secrets \
  --as=system:serviceaccount:juwan:user-rpc \
  --resource-name=jwt-secret -n juwan
# 预期: yes

# 其他 SA 无法读 jwt-secret
kubectl auth can-i get secrets \
  --as=system:serviceaccount:juwan:default \
  --resource-name=jwt-secret -n juwan
# 预期: no
```

### 日志查看

```bash
# user-rpc 日志
kubectl logs -n juwan -l app=user-rpc -f

# Envoy 日志
kubectl logs -n juwan -l app=envoy-gateway -f

# 特定 Pod 日志
kubectl logs -n juwan <pod-name> --all-containers=true -f
```

### 环境变量验证

```bash
# 检查 JWT_SECRET_KEY 已注入
kubectl exec -it $(kubectl get pod -n juwan -l app=user-rpc -o name | head -1) \
  -n juwan -- env | grep JWT_SECRET_KEY
```

### Redis 验证

```bash
# 连接到 Redis Cluster
kubectl run redis-cli --image=redis:latest --rm -it --restart=Never -- \
  redis-cli -h user-redis.juwan:6379 -c CLUSTER INFO

# 测试键操作
kubectl run redis-cli --image=redis:latest --rm -it --restart=Never -- \
  redis-cli -h user-redis.juwan:6379 -c GET jwt:user:test-user-id
```

### ETCD 加密配置

```bash
# 1. 在 Control Plane 节点生成密钥
head -c 32 /dev/urandom | base64

# 2. 编辑 kube-apiserver 清单
sudo nano /etc/kubernetes/manifests/kube-apiserver.yaml

# 添加参数:
--encryption-provider-config=/etc/kubernetes/encryption-config.yaml

# 3. 创建加密配置文件
cat <<EOF | sudo tee /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <BASE64_KEY>
      - identity: {}
EOF

# 4. 验证加密
kubectl create secret generic test-encryption -n juwan --from-literal=key=value
sudo ETCDCTL_API=3 etcdctl --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --endpoints=127.0.0.1:2379 \
  get /registry/secrets/juwan/test-encryption | od -A x -t x1z
```

### 故障排查

```bash
# Pod 无法启动？查看事件
kubectl describe pod <pod-name> -n juwan

# 权限被拒绝？检查 RBAC
kubectl get rolebinding -n juwan -o wide
kubectl describe rolebinding jwt-secret-reader-user-rpc -n juwan

# 无法挂载 Secret？检查 Secret 存在性
kubectl get secret jwt-secret -n juwan -o yaml

# Redis 连接错误？测试连通性
kubectl exec -it <user-rpc-pod> -n juwan -- \
  redis-cli -h user-redis.juwan:6379 PING
```

## JWT Manager API 速查

### JwtManager 方法

```go
// 生成新令牌
token, err := svcCtx.JwtManager.New(ctx, userID, email, name)

// 验证令牌
claims, err := svcCtx.JwtManager.Valid(ctx, token)

// 刷新令牌（如果过期但 Redis 仍有数据）
newToken, err := svcCtx.JwtManager.Renew(ctx, token)

// 提取声明（不验证签名）
claims, err := svcCtx.JwtManager.Extract(ctx, token)

// 检查令牌是否存在于 Redis
exists, err := svcCtx.JwtManager.Exists(ctx, token)

// 撤销令牌（登出）
err := svcCtx.JwtManager.Revoke(ctx, userID, token)

// 获取用户当前令牌
token, err := svcCtx.JwtManager.GetUserToken(ctx, userID)

// 将声明转换为载荷
payload := svcCtx.JwtManager.ClaimsToPayload(claims)
```

## 配置文件位置

| 配置 | 位置 | 关键参数 |
|-----|------|--------|
| JWT Secret | `deploy/k8s/secrets/jwt-secret.yaml` | `secret-key` |
| user-rpc 配置 | `app/users/rpc/etc/pb.yaml` | `JWT.SecretKey`, `REDIS_HOST` |
| Envoy 配置 | `deploy/k8s/envoy/envoy.yaml` | CSRF 验证 Lua 代码 |
| ETCD 加密 | `/etc/kubernetes/encryption-config.yaml`（Control Plane） | `secret` (32字节密钥) |

## 关键参数速查

```yaml
# JWT 令牌有效期
Token Exp: 7 days

# Redis 存储 TTL
Redis TTL: 30 days

# 可刷新时间窗口
Refresh Window: 30 days - 7 days = 23 days

# CSRF Token 位置
Cookie: csrf_token=...
Header: X-CSRF-Token: ...

# ETCD 加密算法
Algorithm: AES-CBC
Key Size: 256 bits (32 bytes)
Encoding: Base64

# Secret 挂载方式
Method: volumeMount (read-only)
或
Method: valueFrom.secretKeyRef
```

## 常见问题速查

| 问题 | 排查命令 | 解决方案 |
|-----|--------|--------|
| Pod 无法启动 | `kubectl describe pod` | 检查 Secret/RBAC |
| 权限被拒绝 | `kubectl auth can-i get secrets` | 验证 RBAC 绑定 |
| Redis 连接失败 | `redis-cli PING` | 检查 Redis Pods |
| JWT 验证失败 | 查看 Pod 日志 | 检查 Redis 中的令牌 |
| CSRF 验证失败 | 查看 Envoy 日志 | 检查 Cookie/Header 匹配 |
| ETCD 加密失败 | `kubectl get secret` | 检查 kube-apiserver 启动参数 |

## 部署检查清单 (5分钟版)

```bash
# 第1步: 部署 Secret (10秒)
kubectl apply -f deploy/k8s/secrets/jwt-secret.yaml && sleep 5

# 第2步: 验证 Secret (10秒)
kubectl get secret jwt-secret -n juwan && echo "✓ Secret 已创建"

# 第3步: 验证 RBAC (10秒)
kubectl get role jwt-secret-reader -n juwan && echo "✓ RBAC 已配置"

# 第4步: 更新 Deployments (20秒)
kubectl apply -f deploy/k8s/service/user/user-rpc.yaml
kubectl apply -f deploy/k8s/envoy/envoy.yaml

# 第5步: 等待 Pods 启动 (30秒)
kubectl rollout status deployment/user-rpc -n juwan
kubectl rollout status deployment/envoy-gateway -n juwan

# 第6步: 快速功能测试 (2分钟)
# 创建一个令牌并验证可读取
REDIS_POD=$(kubectl get pod -n juwan -l redis=user-redis -o name | head -1)
kubectl exec -it $REDIS_POD -n juwan -- redis-cli KEYS "jwt:*"
```

## 密钥轮换步骤

```bash
# 1. 生成新密钥
NEW_KEY=$(head -c 32 /dev/urandom | base64)

# 2. 更新 Secret
kubectl create secret generic jwt-secret \
  --from-literal=secret-key=$NEW_KEY \
  --dry-run=client -o yaml | kubectl apply -f -

# 3. 重启 Pods（自动挂载新 Secret）
kubectl rollout restart deployment/user-rpc -n juwan
kubectl rollout restart deployment/envoy-gateway -n juwan

# 4. 等待 Pods 启动
kubectl rollout status deployment/user-rpc -n juwan
kubectl rollout status deployment/envoy-gateway -n juwan

# 5. 旧令牌现在需要刷新或重新登录
```

## 文档地图

```
deploy/k8s/secrets/
├── jwt-secret.yaml          ← Secrets + RBAC 配置
├── README.md                ← 开始阅读（快速指南）
├── SUMMARY.md               ← 本文件（系统概览）
├── DEPLOYMENT.md            ← 详细部署步骤（12步）
├── ENCRYPTION.md            ← ETCD 加密详细指南
├── VERIFICATION.md          ← 完整验证清单（12部分）
└── QUICK_REFERENCE.md       ← 本快速参考卡片

app/users/api/
└── INTEGRATION.md           ← JWT 代码集成指南

app/users/rpc/
├── internal/utils/jwt.go                    ← JwtManager 实现
├── internal/config/config.go                ← JWT 配置
├── internal/svc/serviceContext.go           ← 依赖注入
└── etc/pb.yaml                              ← 运行时配置
```

## 关键时间点

| 阶段 | 时间 | 操作 |
|-----|------|------|
| 令牌签发 | T0 | 生成 JWT，过期时间 = T0 + 7天 |
| | | 在 Redis 存储，TTL = 30天 |
| Token 过期 | T0 + 7天 | JWT 验证失败 |
| 令牌刷新 | T0 + 7天到T0 + 30天 | 如果 Redis 仍有数据，生成新令牌 |
| 完全失效 | T0 + 30天 | Redis 删除，无法再刷新 |
| 重新登录 | T0 + 30天+ | 用户需要重新登录 |

## 性能提示

```bash
# 高并发下优化 Redis 连接
# 在 pb.yaml 中调整:
CacheConf:
  - Host: "user-redis.juwan:6379"
    Type: "cluster"
    MaxConnections: 100
    ConnectionPoolSize: 50

# 监控 JWT 验证吞吐量
# 在 Prometheus 查询:
rate(jwt_validations_total[5m])
rate(jwt_refresh_total[5m])
```

## 安全提示

✅ **必做**
- [ ] 定期轮换 JWT 秘钥（季度）
- [ ] 定期轮换 ETCD 加密密钥（年度）
- [ ] 备份加密密钥到安全位置
- [ ] 启用审计日志
- [ ] 监控异常的令牌验证失败

❌ **禁止**
- [ ] 不要在日志中输出 JWT 秘钥
- [ ] 不要在代码库中存储密钥
- [ ] 不要发送明文密钥到 Slack/Email
- [ ] 不要在多个环境间共享密钥

## 版本信息

```
Kubernetes: 1.24+
Go-zero: v1.10.0+
Redis: 7.0+
ETCD: 3.5+
Envoy: v1.32.2+
```

## 支持和反馈

遇到问题？按优先级检查：

1. **运行验证脚本**
   ```bash
   chmod +x deploy/k8s/secrets/verify-jwt-setup.sh
   ./deploy/k8s/secrets/verify-jwt-setup.sh
   ```

2. **查看日志**
   ```bash
   kubectl logs -n juwan -l app=user-rpc -f
   ```

3. **阅读 VERIFICATION.md**
   - 第1-5部分: 基础配置
   - 第6-8部分: 网络和监控
   - 第9部分: ETCD 加密
   - 第11部分: 故障排查

4. **详细指南**
   - DEPLOYMENT.md - 完整步骤
   - INTEGRATION.md - 代码集成
   - ENCRYPTION.md - 加密配置
