# Apollo Router 配置(v2.1 M2 + M3 安全加固) # # Router 作为唯一的外部 GraphQL 入口,替代 3 个 BFF 的手动聚合。 # 前端 → Router(GraphQL)→ 各子图(/graphql) # 内部调用(后端 → 后端)仍走 gRPC(ADR-037)。 # # 端口:3000(GraphQL)/ 8088(健康检查) # 镜像:ghcr.io/apollographql/router:v1.45.0 # # v2.1 M3 安全加固: # - APQ + manifest 校验(生产拒绝未知 hash) # - 深度/复杂度限制 # - 生产关闭 introspection(通过环境变量控制) # - 生产仅允许 POST(csrf.enabled 阻止 GET 查询) supergraph: listen: 0.0.0.0:3000 path: /graphql # 生产关闭 introspection(APOLLO_ROUTER_INTROSPECTION=false) # 开发默认 true 便于调试 introspection: ${env.APOLLO_ROUTER_INTROSPECTION::true} # 持久化查询(v2.1 M3 安全加固) # 关联:portal-shell spec §4.3 # - enabled: 启用 APQ(接受 hash-only 请求) # - require_manifest: 生产设为 true,仅接受 manifest 内的 hash # - manifest_path: manifest 文件路径(由 portal-shell 构建产物挂载) persisted_queries: enabled: true require_manifest: ${env.APOLLO_REQUIRE_PQ_MANIFEST::false} manifest_path: /etc/apollo-router/pq-manifest.json # 查询限制(v2.1 M3 安全加固) # 关联:portal-shell spec §5.1 # - max_depth: 最大嵌套深度 10(防止递归攻击) # - max_cost: 最大查询复杂度 1000(防止放大攻击) # - max_batch_size: 批量查询上限 5(防止 batch 攻击) limits: max_depth: 10 max_cost: 1000 max_batch_size: 5 # Sandbox 模式:支持开发和调试(v1.45 中 sandbox 已合并到 homepage) homepage: enabled: true # CORS:允许前端 portal 访问 cors: origins: - "http://localhost:4000" - "http://localhost:4001" - "http://localhost:4002" - "http://localhost:4003" - "http://localhost:4010" - "http://teacher-portal:4000" - "http://student-portal:4001" - "http://parent-portal:4002" - "http://admin-portal:4003" - "http://portal-shell:4010" methods: - GET - POST - OPTIONS allow_credentials: true allow_headers: - Authorization - Content-Type - X-Request-Id - X-Expected-Version - If-Match # 向所有子图注入 Router-Authorization Header(ADR-036) # 子图的 RouterAuthGuard 校验此 Header,拒绝非 Router 的直接 GraphQL 请求 # 同时透传用户身份头(x-user-id / x-user-role)与 Authorization 到子图, # 供 iam/core-edu/msg 等子图做用户级鉴权(M8:portal-shell 查询走 Router) headers: all: request: - insert: name: "router-authorization" value: "dev-router-secret" - propagate: named: "Authorization" - propagate: named: "x-user-id" - propagate: named: "x-user-role" - propagate: named: "X-Request-Id" # 健康检查 health_check: listen: 0.0.0.0:8088 # 日志(v1.45 使用 telemetry.exporters.logging) telemetry: exporters: logging: stdout: format: json instrumentation: spans: mode: spec_compliant