4. 零信任架构下的API网关角色
说实话,很多团队刚开始搞零信任的时候,第一个想到的就是「搞个API网关吧」。这个想法没错,但容易走偏。我见过不少项目,把网关当成了一个简单的反向代理,或者干脆把它做成了传统的REST API入口——那跟零信任基本没啥关系。
零信任架构里的API网关,它不是一个流量入口那么简单。它得是[email protected]策略执行点,是身份边界和网路边界的交汇处。说白了,网关就是那道大门,但不是谁敲门都开的门,而是得检查身份证、核对访客名单、还要问你今天来干嘛的那种门禁。
4.1 为什么是API网关,而不是传统网关
传统架构下,网关做的事情主要是:负载均衡、限流、协议转换。这些东西零信任里也需要,但远远不够。零信任要求的是持续验证,不是一次性的「你进来吧,后面我就不管了」。
我两年前帮一家金融科技公司做架构改造时,他们原来的API网关就是Nginx+Lua做的一层转发,用户登录后拿一个JWT,后面所有请求全靠这个JWT放行。结果有个内部员工把JWT泄露了,对方拿着那个几乎可以调用所有接口。这就是典型的「一次验证,永远信任」的坑。
零信任下的网关要做几件核心事:
- 身份不间断校验:不只是验证,还得检查设备指纹、行为上下文、环境风险分
- 细粒度授权:不是谁有什么角色就能调什么API,而是每一次请求都要重新评估
- 动态策略下发:策略不能写死在网关配置文件里,得从策略引擎实时拉
- 全量审计日志:每一次授权决策、每一次拒绝都要落日志,不只是成功请求
核心原则:零信任的API网关不再是一个「入口」,而是一个「决策执行点」(PEP)。它不自己做决策,它执行决策引擎下发的指令。
4.2 网关在零信任架构中的三大角色
我通常把零信任下的API网关拆成三个角色来理解,这样架构起来会清晰很多。
| 角色 | 对应能力 | 我的经验 |
|---|---|---|
| 身份验证代理 | 不只是JWT校验,还有设备证书、OAuth2.0、OIDC、SAML等 | 选OIDC是最通用的做法,兼容性好 |
| 策略执行点 | 把请求上下文发给PDP,等决策,然后执行 | 决策时延必须在5ms内,否则网关成瓶颈 |
| 安全屏障 | 防注入、防重放、防CSRF、请求内容校验 | 我在一个项目中漏配了内容校验,结果SQL注入从网关进来了,亏大了 |
身份验证代理
传统的网关可能只验一次。零信任里不行,因为会过期,上下文会变化。我建议的做法是:网关拦截每个请求后,去身份提供者(IdP)那里确认一下这个是不是还在有效期内,发起请求的设备是不是还在可信列表里。
这样做会不会太慢?嗯,这里有个技巧:用缓存加细粒度的失效机制。不是每次都去IdP查,而是把验证结果缓存5秒或者10秒,但一旦有风险事件触发,马上清缓存。
策略执行点
这个词在零信任标准里叫PEP(Policy Enforcement Point),跟PDP(Policy Decision Point)是配对出现的。PEP不自己做决定,它只是把请求的「是谁、在什么设备上、从哪个IP、在什么时间、要访问什么API」这些信息打包发给PDP,然后PDP返回「允许」或「拒绝」。PEP只管执行。
避坑:PEP和PDP之间一定不要用同步RPC。我们曾经用过gRPC同步调用,结果PDP挂了,整个网关也跟着崩了。改成异步+本地缓存后,网关即使断网也能按最后一次的策略规则做降级处理。
安全屏障
这个角色很多人会忽略。网关不光是做权限控制,它还应该帮你挡住那些基础的攻击。SQL注入、XSS、路径穿越这些,网关层面就应该能拦掉大部分。我见过一个团队觉得「反正后面有WAF」,网关只做转发,结果WAF规则没更新,被人绕过了。
// 一个简单的网关请求校验示例(伪代码)
function validateRequest(request) {
// 1. 校验身份
if (!verifyIdentity(request., request.deviceFingerprint)) {
return deny("身份验证失败");
}
// 2. 请求PDP做授权决策
const decision = await callPDP({
user: request.userId,
role: request.role,
action: request.method,
resource: request.path,
context: {
deviceRisk: request.device.riskScore,
location: request.geo,
time: Date.now()
}
});
// 3. 执行决策
if (decision !== "allow") {
audit.log("拒绝", request, decision.reason);
return deny(decision.reason);
}
// 4. 内容安全检查
if (hasMaliciousContent(request.body)) {
audit.log("拦截攻击请求", request);
return deny("请求内容不合法");
}
// 5. 放行
return forwardToBackend(request);
}
4.3 网关的架构位置
零信任架构下,网关应该部署在哪?我见过两种方案:
- 南北向网关:部署在公网入口,处理外部客户端的请求
- 东西向网关:部署在服务网格里,处理微服务之间的调用
我的经验是,初期先搞定南北向,因为外部请求的风险最高。等内部服务治理成熟了,再上东西向的服务网格网关。否则一步到位搞网格,团队学习成本太高,容易失控。
注意:东西向网关的引入会显著增加服务间调用的延迟。我建议先做好服务水平指标(SLI),如果延迟增量超过2ms,就要考虑是不是用了太重的东西向方案。有些团队直接用sidecar代理,单次调用延迟多了5-8ms,这就有点过了。
4.4 网关的避坑指南
这些年我做零信任网关踩过的坑,大概能列成下面这几点。你想想看,如果你们正在搭网关,是不是也遇到过类似的问题?
- 不要把网关做成单一故障点:网关必须多副本部署,而且要支持优雅降级。我曾经遇到过网关挂了以后,所有业务都断了工的事。后来我们加了本地决策缓存和熔断逻辑,就算PDP挂了,网关也能按最后一次的策略继续运行一段时间。
- 策略下发不要用推模式,用拉模式:PDP主动推策略给网关,网络一抖就丢失。改成网关定期拉取或长轮询后,稳定多了。
- 审计日志不能只记允许的请求:零信任最重要的日志是被拒绝的请求。分析这些日志,你能发现很多异常行为。我们有一次就是从拒绝日志里发现了一个暴力破解的IP段。
- 别忘了HTTPS卸载:网关要处理好SSL/TLS卸载,否则后面每个服务都得自己管证书。但注意,卸载后的内部流量在服务间传输时仍然要走mTLS,不能裸着跑。
小技巧:网关的本地策略缓存不要存活太久。我一般设5分钟,同时监听PDP的变更事件。如果有紧急策略变更(比如发现某个API正在被攻击),可以立刻触发缓存刷新。这样既保证了性能,又不会错过紧急变更。
4.5 选型建议
市面上的API网关很多,但适合零信任的并不多。我个人的选型标准大致是这样:
| 需求 | 推荐方案 | 理由 |
|---|---|---|
| 轻量级、插件扩展 | Kong / Apache APISIX | 插件机制完善,容易集成自定义策略引擎 |
| 云原生、服务网格 | Envoy + Istio | 东西向网关首选,稳定性和性能都很好 |
| 企业级、开箱即用 | Azure API Management / AWS API Gateway | 内置了OAuth2、OIDC支持,零成本集成 |
嗯,我在最后想强调一点:网关只是零信任中的一环。它再强大,如果后面的服务不受信任,或者身份体系没建好,那网关就是个摆设。下一部分我们会聊到,如何在网关层面做细粒度的RBAC策略定义和动态下放,让网关真正成为一个「内外有别、时刻警惕」的守门员。