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 网关的架构位置

零信任架构下,网关应该部署在哪?我见过两种方案:

  • 南北向网关:部署在公网入口,处理外部客户端的请求
  • 东西向网关:部署在服务网格里,处理微服务之间的调用

我的经验是,初期先搞定南北向,因为外部请求的风险最高。等内部服务治理成熟了,再上东西向的服务网格网关。否则一步到位搞网格,团队学习成本太高,容易失控。

零信任API网关架构位置图 外部用户/客户端 南北向API网关 策略执行点(PEP) PDP决策引擎 内部服务网络 服务A 服务B 服务C 东西向网关 网关分层:南北向处理外部请求 东西向处理内部服务间调用

注意:东西向网关的引入会显著增加服务间调用的延迟。我建议先做好服务水平指标(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策略定义和动态下放,让网关真正成为一个「内外有别、时刻警惕」的守门员。