This commit is contained in:
wwweww
2026-02-23 20:36:21 +08:00
parent 4898aecd3b
commit fdbcde13b2
52 changed files with 11263 additions and 194 deletions
+371
View File
@@ -0,0 +1,371 @@
# Envoy 配置完整清单
## 📋 配置文件清单
### 1. Proto 更新
- **文件**: [desc/rpc/users.proto](../../desc/rpc/users.proto)
- **更改**: 添加了两个 RPC 方法
- `ValidateToken()`: 验证 token 是否有效(检查黑名单)
- `CheckPermission()`: 检查用户权限
### 2. Envoy 部署
- **配置文件**: [envoy.yaml](./envoy.yaml)
- HTTP 监听器(端口 8080
- HTTPS 监听器(端口 8443
- JWT 验证过滤器
- CSRF 防护过滤器
- 速率限制(DDoS 防护)
- 路由配置
- **K8s 部署**: [../k8s/envoy-gateway.yaml](../k8s/envoy-gateway.yaml)
- 2 个副本
- 负载均衡器服务
- Service Account 和 RBAC
- Network Policy
- ConfigMap 用于配置管理
### 3. 工具代码
- **JWKS 生成**: [app/users/rpc/internal/utils/jwks.go](../../app/users/rpc/internal/utils/jwks.go)
- `GenerateJWKSFromSecret()`: 从 JWT 密钥生成 JWKS
- `GenerateJWKSEndpoint()`: 生成 JSON 输出供 Envoy 使用
- `ExtractTokenMetadata()`: 提取 token 元数据
### 4. Dockerfile
- **文件**: [Dockerfile](./Dockerfile)
- **用途**: 构建 Envoy 容器镜像
### 5. 脚本
- **文件**: [generate-jwks.sh](./generate-jwks.sh)
- **用途**: 快速生成 JWKS JSON 文件
### 6. 文档
- **文件**: [ENVOY_CONFIG_GUIDE.md](./ENVOY_CONFIG_GUIDE.md)
- **内容**: 详细的配置和部署指南
---
## 🚀 快速部署步骤
### 步骤 1: 生成 TLS 证书
```bash
# 测试环境:生成自签名证书
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
```bash
# 应用部署文件
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`
```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`
```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: 构建并推送容器镜像
```bash
# 构建 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
```bash
# 获取 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 访问受保护资源
```bash
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
curl -k -X GET "https://$ENVOY_IP:443/api/v1/users/123" \
-H "Authorization: Bearer $TOKEN" | jq .
```
### 3. 验证 CSRF 防护
```bash
# 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 容器运行正常
```bash
kubectl logs -n juwan -l app=envoy-gateway
```
- [ ] JWKS 端点可访问
```bash
kubectl exec -it -n juwan <envoy-pod> -- \
curl http://user-rpc-svc:9001/.well-known/jwks.json
```
- [ ] 后端服务健康
```bash
kubectl exec -it -n juwan <envoy-pod> -- \
curl http://user-api-svc:8888/health
```
- [ ] JWT 验证工作
```bash
# 不带 token 访问受保护资源应返回 401
curl -k https://api.juwan.local/api/v1/users/123
```
- [ ] CSRF 防护生效
```bash
# 缺少 Origin header 的 POST 应被拒绝
curl -k -X POST https://api.juwan.local/api/v1/users/logout \
-H "Authorization: Bearer $TOKEN"
```
---
## 🔧 配置调整
### 修改 JWT 密钥
```bash
# 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
```bash
kubectl edit cm envoy-config -n juwan
```
修改 `token_bucket` 参数:
```yaml
token_bucket:
max_tokens: 5000 # 降低限制
tokens_per_fill: 5000
fill_interval: 1s
```
### 添加信任的 CSRF 来源
编辑 ConfigMap
```yaml
additional_origins:
- exact: "https://admin.juwan.local"
- exact: "https://web.juwan.local"
- prefix: "https://app.juwan.local" # 支持前缀匹配
```
---
## 📈 监控和日志
### 查看 Envoy 统计
```bash
kubectl port-forward -n juwan svc/envoy-gateway 9901:9901
curl localhost:9901/stats | grep -E "(jwt_authn|csrf|http_ratelimit)"
```
### 实时日志
```bash
kubectl logs -n juwan -l app=envoy-gateway -f
# 查看特定日志行
kubectl logs -n juwan -l app=envoy-gateway | grep "401\|403"
```
### 监控指标(集成 Prometheus
```yaml
# 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 定义(已更新)
```
---
## 🤔 常见问题
1. **Envoy 无法连接到后端服务**
- 检查 K8s Service DNS: `user-api-svc.juwan.svc.cluster.local`
- 验证 NetworkPolicy 允许流量
2. **JWT 验证失败**
- 确保 JWT_SECRET_KEY 一致
- 检查 JWKS 端点是否可访问
- 查看 Envoy 日志: `grep "jwt_authn" envoy.log`
3. **CSRF 防护过于严格**
- 在 `additional_origins` 中添加允许的来源
- 对于单页应用,确保发送 `Origin` header
4. **速率限制阻止正常流量**
- 增加 `max_tokens` 和 `tokens_per_fill`
- 针对特定客户端配置不同的限制
---
## 📞 获取帮助
- 查看 [Envoy 官方文档](https://www.envoyproxy.io/docs)
- 查看 [JWT 规范](https://tools.ietf.org/html/rfc7519)
- 检查 [CSRF 防护最佳实践](https://owasp.org/www-community/attacks/csrf)