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

508 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 完整部署验证清单
完成所有部署后使用此清单验证系统是否正确配置和运行。
## 第一部分:基础设施验证
### Secret 和 RBAC 创建
```bash
# 检查 Secret 已创建
kubectl get secret -n juwan | grep jwt-secret
# 预期输出: jwt-secret Created
# 查看 Secret 详情(不显示敏感数据)
kubectl describe secret jwt-secret -n juwan
# 应该看到:
# Name: jwt-secret
# Namespace: juwan
# Type: Opaque
# Data
# ====
# secret-key: <encrypted>
# 验证 Secret 内容已正确加载
kubectl get secret jwt-secret -n juwan -o jsonpath='{.data.secret-key}' | base64 -d | wc -c
# 预期输出: 应该是 32 个字符(32 字节密钥的 Base64 解码)
```
### ServiceAccount 验证
```bash
# 检查 user-rpc ServiceAccount
kubectl get sa user-rpc -n juwan
kubectl describe sa user-rpc -n juwan
# 应该显示正确的 Secrets 挂载
# 检查 envoy-gateway ServiceAccount
kubectl get sa envoy-gateway -n juwan
kubectl describe sa envoy-gateway -n juwan
```
### RBAC 权限验证
```bash
# 检查 Role 定义
kubectl get role -n juwan -l app=jwt-secret-reader
kubectl describe role jwt-secret-reader -n juwan
# 应该显示:
# PolicyRule:
# Resources Non-Resource URLs Resource Names Verbs
# --------- ----------------- -------------- -----
# secrets [] [jwt-secret] [get]
# 检查 RoleBindings
kubectl get rolebinding -n juwan | grep jwt-secret-reader
# 应该显示两个绑定: jwt-secret-reader-user-rpc 和 jwt-secret-reader-envoy-gateway
# 验证每个 RoleBinding
kubectl describe rolebinding jwt-secret-reader-user-rpc -n juwan
kubectl describe rolebinding jwt-secret-reader-envoy-gateway -n juwan
```
## 第二部分:权限测试
### 权限允许测试
```bash
# 测试 user-rpc 可以读 jwt-secret
kubectl auth can-i get secrets \
--as=system:serviceaccount:juwan:user-rpc \
--resource-name=jwt-secret \
-n juwan
# 预期输出: yes
# 测试 envoy-gateway 可以读 jwt-secret
kubectl auth can-i get secrets \
--as=system:serviceaccount:juwan:envoy-gateway \
--resource-name=jwt-secret \
-n juwan
# 预期输出: yes
# 测试 user-rpc 无法读其他 Secrets
kubectl auth can-i get secrets \
--as=system:serviceaccount:juwan:user-rpc \
-n juwan
# 预期输出: no
# 测试其他 ServiceAccount 无法读 jwt-secret
kubectl auth can-i get secrets \
--as=system:serviceaccount:juwan:default \
--resource-name=jwt-secret \
-n juwan
# 预期输出: no
```
## 第三部分:Deployment 配置验证
### user-rpc Deployment 验证
```bash
# 检查 ServiceAccountName 是否正确设置
kubectl get deployment user-rpc -n juwan -o jsonpath='{.spec.template.spec.serviceAccountName}'
# 预期输出: user-rpc
# 检查是否包含所有必需的环境变量
kubectl get deployment user-rpc -n juwan -o yaml | grep -A 20 "env:"
# 应该包括:
# - name: JWT_SECRET_KEY
# valueFrom:
# secretKeyRef:
# name: jwt-secret
# key: secret-key
# 检查 Pod 是否正在运行
kubectl get pods -n juwan -l app=user-rpc
# 应该显示至少 3 个 Running 的 Pod
# 验证 Pod 已加载 Secret(在 Pod 中执行)
kubectl exec -it $(kubectl get pod -n juwan -l app=user-rpc -o name | head -1) -n juwan -- env | grep -i jwt
# 应该输出环境变量,例如:
# JWT_SECRET_KEY=your-secret-jwt-key-change-this-in-production
```
### Envoy Gateway Deployment 验证
```bash
# 检查 ServiceAccountName 是否正确设置
kubectl get deployment envoy-gateway -n juwan -o jsonpath='{.spec.template.spec.serviceAccountName}'
# 预期输出: envoy-gateway
# 检查 Pod 是否正在运行
kubectl get pods -n juwan -l app=envoy-gateway
# 应该显示 Running 的 Pod
# 检查 Envoy 日志
kubectl logs -n juwan -l app=envoy-gateway
# 应该看到启动日志,没有权限相关错误
```
## 第四部分:Redis 连接验证
### Redis Cluster 验证
```bash
# 检查 RedisCluster CRD 状态
kubectl get rediscluster -n juwan
# 应该显示 user-redisStatus 应该是 Healthy
# 详细查看 RedisCluster 状态
kubectl describe rediscluster user-redis -n juwan
# 应该显示:
# Status:
# Cluster Status: Healthy
# Nodes Ready: 3/3
# Master: 1
# Replicas: 2
# 检查 Redis Pods
kubectl get pods -n juwan | grep redis
# 应该显示 3 个 Redis Pod,都在 Running 状态
# 测试 Redis 连接
kubectl run redis-cli --image=redis:latest --rm -it --restart=Never -- \
redis-cli -h user-redis.juwan -c CLUSTER INFO
# 应该看到集群信息,cluster_state:ok 表示集群健康
```
## 第五部分:应用启动日志检查
### user-rpc 启动日志
```bash
# 查看 user-rpc Pods 的启动日志
kubectl logs -n juwan -l app=user-rpc --all-containers=true
# 应该包含类似以下消息:
# - "Starting gRPC server on 0.0.0.0:9001"
# - "Redis Cluster connected successfully" 或 JWT Manager 初始化成功
# - "Listening on metrics port 4001"
# 如果有错误,查看详细日志
kubectl logs -n juwan -l app=user-rpc -f --all-containers=true
```
### Envoy 启动日志
```bash
# 查看 Envoy 启动日志
kubectl logs -n juwan -l app=envoy-gateway
# 应该包含:
# - "[info] Configuration: /etc/envoy/envoy.yaml"
# - "[info] listener listening on 0.0.0.0:8080"
# - 没有权限相关错误
```
## 第六部分:网络和服务发现验证
### Service 验证
```bash
# 检查 user-rpc-svc
kubectl get svc user-rpc-svc -n juwan
# 应该显示 ClusterIP 和两个端口 (9001/rpc 和 4001/metrics)
# 检查 Envoy Gateway Service
kubectl get svc envoy-gateway -n juwan
# 应该显示 ClusterIP 和端口 80
# 检查 Redis Service
kubectl get svc -n juwan | grep redis
# 应该显示 user-redisClusterIP)服务
```
### DNS 解析验证
```bash
# 测试服务名称解析
kubectl run -it --rm debug --image=busybox --restart=Never -- \
nslookup user-rpc-svc.juwan.svc.cluster.local
# 应该返回 ClusterIP 地址
kubectl run -it --rm debug --image=busybox --restart=Never -- \
nslookup user-redis.juwan.svc.cluster.local
# 应该返回 ClusterIP 地址
```
## 第七部分:监控和指标验证
### Prometheus 指标收集
```bash
# 检查 Prometheus 是否在收集指标
kubectl port-forward -n monitoring svc/prometheus 9090:9090 &
# 打开浏览器访问 http://localhost:9090
# 查看 Status > Targets
# 应该看到 user-rpc-svc:4001 目标显示为 UP
# 查询一个指标
curl 'http://localhost:9090/api/v1/query?query=up{job="kubernetes-pods"}'
# 应该返回 user-rpc 的指标数据
# 关闭端口转发
kill %1
```
### 测试源代码级指标端点
```bash
# 从 user-rpc Pod 直接访问指标端点
kubectl port-forward -n juwan svc/user-rpc-svc 4001:4001 &
# 测试指标端点
curl http://localhost:4001/metrics
# 应该看到 Prometheus 格式的指标,例如:
# # HELP go_goroutines Number of goroutines that currently exist.
# # TYPE go_goroutines gauge
# go_goroutines 25
# 关闭端口转发
kill %1
```
## 第八部分:日志聚合验证(Loki)
```bash
# 检查 Loki 是否正确接收日志
kubectl port-forward -n monitoring svc/loki 3100:3100 &
# 查询日志
curl 'http://localhost:3100/loki/api/v1/query_range?query={job="kubernetes-pods"}&start=0&end=9999999999'
# 应该返回最近的日志条目
# 检查特定应用的日志
curl 'http://localhost:3100/loki/api/v1/query_range?query={app="user-rpc"}&start=0&end=9999999999'
kill %1
```
## 第九部分:ETCD 加密验证
如果已启用 ETCD 加密,执行以下验证:
```bash
# 从 control plane 节点
ssh <control-plane-node>
# 检查 ETCD 配置
sudo cat /etc/kubernetes/encryption-config.yaml | head -20
# 验证 kube-apiserver 正在使用加密配置
sudo ps aux | grep kube-apiserver | grep encryption-provider
# 创建新 Secret 进行测试
kubectl create secret generic test-encryption -n juwan --from-literal=key=value
# 检查 ETCD 中的数据是否加密
# 注意:如果加密正确,数据应该不可读
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
# 输出应该是二进制数据,不可读(表示已加密)
# 或者使用十六进制 dump
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 -v
```
## 第十部分:功能测试
### JWT 令牌生成和验证测试
如果已实现 JWT handlers,测试完整流程:
```bash
# 1. 前向 user-api 服务
kubectl port-forward -n juwan svc/user-api-svc 8888:8888 &
# 2. 调用登录端点获取令牌
TOKEN=$(curl -X POST http://localhost:8888/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"password"}' \
| jq -r '.token')
echo "Token: $TOKEN"
# 3. 使用令牌访问受保护的端点
curl -H "Authorization: Bearer $TOKEN" http://localhost:8888/api/v1/users/me
# 4. 测试令牌刷新
curl -X POST http://localhost:8888/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-d "{\"token\":\"$TOKEN\"}"
# 5. 测试无效令牌
curl -H "Authorization: Bearer invalid-token" http://localhost:8888/api/v1/users/me
# 应该返回 401 Unauthorized
kill %1
```
### CSRF 保护测试
```bash
# 1. 前向 Envoy Gateway
kubectl port-forward -n juwan svc/envoy-gateway 8080:80 &
# 2. 获取 CSRF 令牌(安全方法)
curl -i http://localhost:8080/
# 查看响应头中的 Set-Cookie,应该包含 csrf_token
# 3. 提取 CSRF 令牌
CSRF_TOKEN=$(curl -i http://localhost:8080/ 2>/dev/null | grep -i csrf_token | sed 's/.*csrf_token=//;s/;.*//')
# 4. 使用 CSRF 令牌进行 POST 请求
curl -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-H "Cookie: csrf_token=$CSRF_TOKEN" \
-H "X-CSRF-Token: $CSRF_TOKEN" \
-d '{"email":"user@example.com","password":"password"}'
# 5. 测试无效 CSRF 令牌(应该返回 403)
curl -X POST http://localhost:8080/api/v1/auth/login \
-H "Cookie: csrf_token=valid_token" \
-H "X-CSRF-Token: invalid_token" \
-d '{"email":"user@example.com","password":"password"}'
# 应该返回 403 Forbidden
kill %1
```
## 第十一部分:故障排查
如果任何验证失败,运行以下诊断:
### Pod 无法启动
```bash
# 显示 Pod 事件
kubectl describe pod <pod-name> -n juwan
# 查看完整日志(包括初始化容器)
kubectl logs <pod-name> -n juwan --all-containers=true --previous
# 检查 Pod 资源限制是否导致 OOMKilled
kubectl get event -n juwan --sort-by='.lastTimestamp'
```
### 权限被拒绝错误
```bash
# 验证 ServiceAccount 是否正确
kubectl get pod <pod-name> -n juwan -o jsonpath='{.spec.serviceAccountName}'
# 检查 RBAC 绑定
kubectl get rolebinding -n juwan -o wide
# 手动测试权限
kubectl auth can-i get secrets \
--as=system:serviceaccount:juwan:user-rpc \
-n juwan
```
### Redis 连接错误
```bash
# 检查 Redis Pods 状态
kubectl get pods -n juwan -l redis=user-redis
# 查看 Redis 日志
kubectl logs -n juwan -l redis=user-redis
# 测试 Redis 连接(从 user-rpc Pod
kubectl exec -it <user-rpc-pod> -n juwan -- \
redis-cli -h user-redis.juwan:6379 PING
# 应该返回 PONG
```
### ETCD 加密问题
```bash
# 验证加密配置
kubectl get secret jwt-secret -n juwan -o json | jq '.data'
# 如果 ETCD 加密启用,直接读取 ETCD 的数据应该是二进制的
# 如果看到明文,说明加密未启用或配置不正确
```
## 第十二部分:清理测试资源
```bash
# 删除测试 Secrets
kubectl delete secret test-encryption test-secret -n juwan --ignore-not-found
# 清理前转发的端口
lsof -i :9090 :3100 :8888 :8080 | grep LISTEN | awk '{print $2}' | xargs kill -9
```
## 快速检查脚本
创建 `verify-jwt-setup.sh` 进行自动化验证:
```bash
#!/bin/bash
namespace="juwan"
echo "=== JWT Setup Verification ==="
# 检查 Secret
echo -n "✓ JWT Secret存在: "
kubectl get secret jwt-secret -n $namespace &>/dev/null && echo "✓" || echo "✗"
# 检查 ServiceAccounts
echo -n "✓ user-rpc ServiceAccount: "
kubectl get sa user-rpc -n $namespace &>/dev/null && echo "✓" || echo "✗"
echo -n "✓ envoy-gateway ServiceAccount: "
kubectl get sa envoy-gateway -n $namespace &>/dev/null && echo "✓" || echo "✗"
# 检查 RBAC
echo -n "✓ JWT RBAC Role: "
kubectl get role jwt-secret-reader -n $namespace &>/dev/null && echo "✓" || echo "✗"
# 检查 Deployments
echo -n "✓ user-rpc Deployment: "
kubectl get deployment user-rpc -n $namespace &>/dev/null && echo "✓" || echo "✗"
echo -n "✓ envoy-gateway Deployment: "
kubectl get deployment envoy-gateway -n $namespace &>/dev/null && echo "✓" || echo "✗"
# 检查 Pods
echo -n "✓ user-rpc Pods运行中: "
[ $(kubectl get pods -n $namespace -l app=user-rpc --field-selector=status.phase=Running --no-headers | wc -l) -ge 1 ] && echo "✓" || echo "✗"
echo -n "✓ envoy-gateway 运行中: "
kubectl get pods -n $namespace -l app=envoy-gateway --field-selector=status.phase=Running &>/dev/null && echo "✓" || echo "✗"
echo "=== Verification Complete ==="
```
运行脚本:
```bash
chmod +x verify-jwt-setup.sh
./verify-jwt-setup.sh
```
## 总结
所有检查项都通过后,JWT + ETCD 加密系统已准备就绪。下一步可以:
1. 集成 JWT 验证到 RPC handlers
2. 实现令牌刷新端点
3. 部署应用代码时启用 JWT 认证
4. 监控令牌生成和验证指标
5. 定期轮换加密密钥和 JWT 秘钥