9.1 KiB
9.1 KiB
Envoy 配置完整清单
📋 配置文件清单
1. Proto 更新
- 文件: desc/rpc/users.proto
- 更改: 添加了两个 RPC 方法
ValidateToken(): 验证 token 是否有效(检查黑名单)CheckPermission(): 检查用户权限
2. Envoy 部署
-
配置文件: envoy.yaml
- HTTP 监听器(端口 8080)
- HTTPS 监听器(端口 8443)
- JWT 验证过滤器
- CSRF 防护过滤器
- 速率限制(DDoS 防护)
- 路由配置
-
K8s 部署: ../k8s/envoy-gateway.yaml
- 2 个副本
- 负载均衡器服务
- Service Account 和 RBAC
- Network Policy
- ConfigMap 用于配置管理
3. 工具代码
- JWKS 生成: app/users/rpc/internal/utils/jwks.go
GenerateJWKSFromSecret(): 从 JWT 密钥生成 JWKSGenerateJWKSEndpoint(): 生成 JSON 输出供 Envoy 使用ExtractTokenMetadata(): 提取 token 元数据
4. Dockerfile
- 文件: Dockerfile
- 用途: 构建 Envoy 容器镜像
5. 脚本
- 文件: generate-jwks.sh
- 用途: 快速生成 JWKS JSON 文件
6. 文档
- 文件: ENVOY_CONFIG_GUIDE.md
- 内容: 详细的配置和部署指南
🚀 快速部署步骤
步骤 1: 生成 TLS 证书
# 测试环境:生成自签名证书
openssl req -x509 -newkey rsa:4096 -keyout tls.key -out tls.crt \
-days 365 -nodes -subj "/CN=api.juwan.local"
# 创建 K8s Secret
kubectl create secret tls envoy-tls \
--cert=tls.crt \
--key=tls.key \
-n juwan
步骤 2: 部署 Envoy Gateway
# 应用部署文件
kubectl apply -f deploy/k8s/envoy-gateway.yaml
# 验证部署
kubectl get pods -n juwan -l app=envoy-gateway
kubectl get svc -n juwan envoy-gateway
# 等待 LoadBalancer 获取外部 IP
kubectl get svc -n juwan envoy-gateway -w
步骤 3: 在 User RPC 中暴露 JWKS 端点
编辑 app/users/rpc/rpcserver.go 或 main.go:
package main
import (
"http"
"os"
"juwan-backend/app/users/rpc/internal/utils"
)
// 在启动 RPC server 前,添加 HTTP 端点
func setupJWKSEndpoint() {
secretKey := os.Getenv("JWT_SECRET_KEY")
if secretKey == "" {
secretKey = "your-default-secret-key"
}
http.HandleFunc("/.well-known/jwks.json", func(w http.ResponseWriter, r *http.Request) {
jwksJSON, err := utils.GenerateJWKSEndpoint(secretKey, "default-key-id")
if err != nil {
http.Error(w, "Failed to generate JWKS", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Cache-Control", "public, max-age=300") // 缓存 5 分钟
w.Write([]byte(jwksJSON))
})
// 在独立的 goroutine 中启动 HTTP 服务器
go func() {
http.ListenAndServe(":8080", nil)
}()
}
func main() {
setupJWKSEndpoint()
// ... 其他 RPC 启动代码 ...
}
步骤 4: 更新 User RPC 配置
编辑 app/users/rpc/etc/pb.yaml:
Name: pb.rpc
ListenOn: 0.0.0.0:9001
Prometheus:
Host: 0.0.0.0
Port: 4001
Path: /metrics
# ... 其他配置 ...
Jwt:
SecretKey: "${JWT_SECRET_KEY:your-secret-jwt-key-change-this-in-production}"
Issuer: "juwan-user-rpc"
步骤 5: 构建并推送容器镜像
# 构建 User API 镜像
docker build -t your-registry/user-api:latest ./app/users/api/
docker push your-registry/user-api:latest
# 构建 User RPC 镜像
docker build -t your-registry/user-rpc:latest ./app/users/rpc/
docker push your-registry/user-rpc:latest
# 构建 Envoy 镜像
docker build -f deploy/envoy/Dockerfile -t your-registry/envoy-gateway:latest .
docker push your-registry/envoy-gateway:latest
步骤 6: 更新 K8s 部署
更新 deploy/k8s/service/user/user-api.yaml 和 user-rpc.yaml,确保使用正确的镜像和环境变量。
🧪 测试流程
1. 登录获取 Token
# 获取 Envoy 外部 IP
ENVOY_IP=$(kubectl get svc -n juwan envoy-gateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
# 登录
curl -k -X POST "https://$ENVOY_IP:443/api/v1/users/login" \
-H "Content-Type: application/json" \
-d '{
"username": "testuser",
"password": "password123"
}' | jq .
# 示例响应:
# {
# "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
# "expires": 1708780800
# }
2. 使用 Token 访问受保护资源
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
curl -k -X GET "https://$ENVOY_IP:443/api/v1/users/123" \
-H "Authorization: Bearer $TOKEN" | jq .
3. 验证 CSRF 防护
# POST 请求必须有正确的 Origin/Referer
curl -k -X POST "https://$ENVOY_IP:443/api/v1/users/logout" \
-H "Authorization: Bearer $TOKEN" \
-H "Origin: https://api.juwan.local" \
-H "Referer: https://api.juwan.local/" \
-H "Content-Type: application/json" \
-d '{"userId": 123}'
📊 验证检查清单
-
Envoy 容器运行正常
kubectl logs -n juwan -l app=envoy-gateway -
JWKS 端点可访问
kubectl exec -it -n juwan <envoy-pod> -- \ curl http://user-rpc-svc:9001/.well-known/jwks.json -
后端服务健康
kubectl exec -it -n juwan <envoy-pod> -- \ curl http://user-api-svc:8888/health -
JWT 验证工作
# 不带 token 访问受保护资源应返回 401 curl -k https://api.juwan.local/api/v1/users/123 -
CSRF 防护生效
# 缺少 Origin header 的 POST 应被拒绝 curl -k -X POST https://api.juwan.local/api/v1/users/logout \ -H "Authorization: Bearer $TOKEN"
🔧 配置调整
修改 JWT 密钥
# 1. 更新 K8s Secret
kubectl patch secret jwt-secret -n juwan \
-p '{"data":{"JWT_SECRET_KEY":"'$(echo -n 'new-secret-key' | base64)'"}}'
# 2. 重启 User RPC 和 Envoy
kubectl rollout restart deployment/user-rpc-svc -n juwan
kubectl rollout restart deployment/envoy-gateway -n juwan
调整 Envoy 速率限制
编辑 ConfigMap:
kubectl edit cm envoy-config -n juwan
修改 token_bucket 参数:
token_bucket:
max_tokens: 5000 # 降低限制
tokens_per_fill: 5000
fill_interval: 1s
添加信任的 CSRF 来源
编辑 ConfigMap:
additional_origins:
- exact: "https://admin.juwan.local"
- exact: "https://web.juwan.local"
- prefix: "https://app.juwan.local" # 支持前缀匹配
📈 监控和日志
查看 Envoy 统计
kubectl port-forward -n juwan svc/envoy-gateway 9901:9901
curl localhost:9901/stats | grep -E "(jwt_authn|csrf|http_ratelimit)"
实时日志
kubectl logs -n juwan -l app=envoy-gateway -f
# 查看特定日志行
kubectl logs -n juwan -l app=envoy-gateway | grep "401\|403"
监控指标(集成 Prometheus)
# prometheus-scrape-config.yaml
- job_name: 'envoy-gateway'
static_configs:
- targets: ['envoy-gateway.juwan.svc.cluster.local:9901']
metrics_path: '/stats/prometheus'
📚 相关文件位置
deploy/
├── envoy/
│ ├── envoy.yaml ← Envoy 核心配置
│ ├── ENVOY_CONFIG_GUIDE.md ← 详细指南
│ ├── generate-jwks.sh ← JWKS 生成脚本
│ ├── Dockerfile ← Envoy 镜像
│ └── QUICK_REFERENCE.md ← 本文件
├── k8s/
│ ├── envoy-gateway.yaml ← K8s 部署清单
│ └── secrets/jwt-secret.yaml ← JWT 密钥配置
└── script/
└── init-secrets.sh ← 初始化脚本
app/users/
├── rpc/
│ ├── internal/utils/
│ │ ├── jwks.go ← JWKS 生成工具
│ │ └── jwt.go ← JWT 管理器
│ └── etc/pb.yaml ← RPC 配置
└── api/
└── etc/user-api.yaml ← API 配置
desc/
└── rpc/users.proto ← Proto 定义(已更新)
🤔 常见问题
-
Envoy 无法连接到后端服务
- 检查 K8s Service DNS:
user-api-svc.juwan.svc.cluster.local - 验证 NetworkPolicy 允许流量
- 检查 K8s Service DNS:
-
JWT 验证失败
- 确保 JWT_SECRET_KEY 一致
- 检查 JWKS 端点是否可访问
- 查看 Envoy 日志:
grep "jwt_authn" envoy.log
-
CSRF 防护过于严格
- 在
additional_origins中添加允许的来源 - 对于单页应用,确保发送
Originheader
- 在
-
速率限制阻止正常流量
- 增加
max_tokens和tokens_per_fill - 针对特定客户端配置不同的限制
- 增加
📞 获取帮助
- 查看 Envoy 官方文档
- 查看 JWT 规范
- 检查 CSRF 防护最佳实践