# 完整部署验证清单

完成所有部署后使用此清单验证系统是否正确配置和运行。

## 第一部分：基础设施验证

### 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-redis，Status 应该是 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-redis（ClusterIP）服务
```

### 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 秘钥
