CI/CD机器身份安全盲区:OIDC信任策略的隐形风险

引言:被忽视的"隐形管理员"
在云原生架构中,安全团队习惯将大量精力投入到人类用户的身份治理上——多因素认证、定期访问审查、离职流程等。然而,一个更隐蔽也更危险的问题正在被系统性地忽视:你系统中权限最高的身份,可能根本没有登录入口。
这里说的正是服务主体(Service Principals)和CI/CD联合身份(Federation)。服务主体是云平台(如Azure AD、AWS IAM、GCP)中为应用程序、服务或自动化工具创建的非人类身份实体。与人类用户账户不同,服务主体通过证书、密钥或令牌进行身份验证,专门用于程序间的自动化交互。从技术渊源来看,服务主体的概念源于操作系统层面的服务账户(Service Account),在云原生时代被提升为一等公民身份实体。在Azure AD(现Microsoft Entra ID)中,服务主体分为三种类型:应用程序类型(与应用注册关联)、托管身份类型(由Azure自动管理生命周期)和旧版类型。AWS中的对应概念是IAM角色(IAM Role),而GCP则使用服务账户(Service Account)。这些身份实体本质上是X.509证书或非对称密钥对的持有者,其身份验证过程不涉及交互式登录,而是通过客户端凭据流(OAuth 2.0 Client Credentials Grant)或实例元数据服务(IMDS)自动完成。正因为这种非交互特性,它们在传统的安全监控体系中几乎是"隐形"的。
联合身份(Federated Identity)则是一种跨信任域的身份验证机制,允许外部身份提供者(如GitHub、GitLab)颁发的令牌在目标云平台中被直接信任,从而无需在云端存储长期凭据。这种机制的核心协议是OpenID Connect(OIDC),它在OAuth 2.0之上增加了身份验证层,使得CI/CD平台可以向云端证明"我是某个特定仓库中运行的某个特定工作流",而云端则根据预配置的信任策略决定是否授予访问权限。OIDC协议的核心创新在于引入了ID Token——一个由身份提供者签名的JWT。在CI/CD联合身份场景中,关键的技术细节在于"发现文档"(Discovery Document)机制:云平台通过访问身份提供者的.well-known/openid-configuration端点获取签名验证所需的公钥(JWKS URI),从而无需预共享密钥即可验证令牌真伪。GitHub Actions的OIDC提供者端点为https://token.actions.githubusercontent.com,其签发的JWT包含约15个标准和自定义声明,令牌有效期通常仅为几分钟。这种短期令牌机制将攻击窗口从传统长期密钥的数月甚至数年压缩到分钟级别,但也将全部安全赌注押在了信任策略的正确配置上。
这些身份不需要密码,不会触发登录告警,也几乎从不出现在季度访问审查的名单上。但正是这些"无脸"的机器身份,往往握有直达生产环境的最高权限。

服务身份为何逃过了访问审查
人类身份与机器身份之间的治理鸿沟
传统的身份治理体系是围绕"人"设计的。员工加入或离开团队时,有明确的入职和离职流程;权限过大时,季度访问审查(Access Review)会将其暴露出来。这套机制经过多年打磨,已经相当成熟。
然而,服务主体和CI/CD管道使用的联合身份,天然地绕过了这些检查点。它们不是"人",因此:
- 不会被纳入以人为中心的访问审查流程
- 没有交互式登录,不会触发基于登录行为的异常检测
- 生命周期与人类账户脱节,往往在项目结束后仍长期存在
结果就是:一个为了让流水线能自动部署而创建的身份,可能拥有生产环境的写入甚至管理权限,却在数月甚至数年间无人过问。值得注意的是,根据行业报告,机器身份的数量已经以10:1甚至更高的比例超过人类身份,而大多数组织的身份治理工具和流程仍然以人类用户为核心设计,这种数量与治理能力的不对称正在成为云安全的最大盲区之一。机器身份治理正在成为一个独立的安全学科。NIST SP 800-207(零信任架构)明确将非人类实体纳入身份验证范畴;CIS Benchmarks为各主要云平台的服务主体和联合身份配置提供了具体的安全基线。Gartner在2023年将"机器身份管理"列为网络安全的关键新兴趋势,预测到2025年,因机器身份管理不善导致的安全事件将增加50%。在工具层面,除了云原生工具外,Venafi、CyberArk和Astrix Security等厂商提供了专门的非人类身份发现、分类和生命周期管理解决方案,涵盖从密钥轮换到权限异常检测的完整治理能力。
权限累积:机器身份的"温水煮青蛙"
更棘手的是,机器身份的权限往往只增不减。每当一条新的部署需求出现,工程师倾向于给现有的服务主体"再加一个权限",而不是做精细化拆分。时间一长,一个原本只负责部署某个微服务的身份,最终积累出跨多个生产系统的超级权限。由于缺乏审查机制,这种权限累积几乎不可见。
这种现象在DevOps文化中尤为普遍。工程团队在追求部署速度和自动化效率时,往往以"先让它跑起来"为优先原则,而权限收窄被视为"以后再做"的优化项。然而,"以后"几乎从不到来——因为没有机制提醒任何人回来清理。与人类用户可能因岗位变动触发权限重新评估不同,机器身份一旦被创建并赋予权限,往往处于"设置后遗忘"(set and forget)状态。这种状态在微服务架构中尤其危险:当一个组织运行着数十甚至数百个微服务,每个服务可能拥有多个CI/CD管道,每条管道又关联着不同的服务主体和联合身份,权限关系的复杂度呈指数级增长。如果缺乏自动化的权限发现和分析工具,安全团队几乎不可能通过手工方式理清这张错综复杂的权限网络。
真正的访问控制藏在OIDC信任策略里
那串决定安全边界的配置字符串
本文的核心观点在于:对于CI/CD联合身份,真正决定谁能到达生产环境的,是OIDC信任策略(Trust Policy)中的那串配置字符串,而非传统意义上的凭据管理。
以GitHub Actions通过OIDC联合到AWS为例,其工作流程如下:当GitHub Actions工作流运行时,GitHub作为OIDC身份提供者(IdP)会为该工作流签发一个短期JWT(JSON Web Token),其中包含丰富的声明(claims),如仓库名(repository)、分支名(ref)、触发事件类型(event_name)、工作流名称(workflow)、运行环境(environment)等。工作流将此令牌发送给AWS STS的AssumeRoleWithWebIdentity接口,AWS验证令牌签名后,将令牌中的声明与角色信任策略中定义的条件进行逐一比对。只有所有条件都满足时,才会颁发临时的云端凭据。
在技术实现层面,AWS Security Token Service(STS)是AWS临时凭据体系的核心组件,AssumeRoleWithWebIdentity是专为OIDC联合身份设计的API。调用该接口时,STS执行一系列严格的验证步骤:首先验证JWT的签名(通过OIDC提供者的JWKS公钥)、检查令牌是否过期(exp声明)、验证受众(aud声明)是否与配置匹配,然后将令牌中的所有声明与角色信任策略的Condition块逐一比对。只有全部验证通过后,STS才会返回一组包含AccessKeyId、SecretAccessKey和SessionToken的临时凭据。这些临时凭据默认有效期为1小时(可配置为15分钟到12小时),过期后必须重新执行令牌交换流程。
这种机制消除了在CI/CD系统中存储长期密钥的需要,显著降低了凭据泄露的风险——但安全边界完全转移到了信任策略的条件配置上。以AWS为例,IAM角色的信任策略是一个JSON文档,其中Principal字段指定OIDC提供者的ARN,Action字段设为sts:AssumeRoleWithWebIdentity,而Condition字段则是安全边界的核心,使用StringEquals或StringLike运算符对JWT中的claims进行匹配。Azure和GCP有类似机制,分别通过Federated Credentials和Workload Identity Federation实现。这串条件字符串就是整个安全边界的最后一道,也是唯一一道防线。
OIDC信任策略配置错误的灾难性后果
问题在于,这类信任策略极易写错,而错误往往难以察觉。常见的配置陷阱包括:
- 通配符过于宽松:使用
repo:org/*而非精确到具体仓库,导致组织内任何仓库的工作流都能获得高权限 - 未限定分支或环境:没有约束
ref条件,使得任意分支(包括攻击者提交的PR分支)都能触发部署 - 主体匹配的字符串前缀漏洞:条件匹配时未正确锚定,可能被相似命名的资源利用
关于字符串前缀漏洞,值得深入解释其技术细节。在AWS IAM条件中,如果使用StringLike运算符配合通配符,如repo:my-org/my-repo*,攻击者可以创建名为my-org/my-repo-malicious的仓库来匹配该条件。更微妙的是,GitHub OIDC令牌的sub声明格式为repo:org/repo:ref:refs/heads/main,如果条件只匹配到repo:org/repo而未包含完整的ref限定,那么任何分支——包括来自fork的pull_request_target事件触发的工作流——都可能满足条件。
这些并非理论上的风险。2023年至2024年间,安全研究社区披露了多起与OIDC信任策略配置相关的漏洞。Praetorian和Chainguard的研究人员分别独立发现,大量GitHub组织的AWS角色信任策略存在过于宽松的subject条件匹配,仅检查组织名而未限定具体仓库。更为严重的是pull_request_target事件的滥用场景:该事件类型的设计初衷是在目标仓库的上下文中运行来自fork的PR代码,这意味着外部攻击者提交的PR可以在受信任仓库的身份上下文中执行,从而匹配OIDC信任策略并获取云端凭据。此类攻击在公开的漏洞赏金报告和安全研究论文中已有详细记录,凸显了信任策略审计的紧迫性。
一旦这串字符串写松了,攻击者无需破解任何密码,只需在符合条件的上下文中运行一段代码,就能"合法地"获得生产环境的最高权限。而这一切不会触发任何登录告警,因为从云平台的视角看,这是一次完全符合信任策略的正常令牌交换——它甚至不会在传统的安全信息和事件管理(SIEM)系统中被标记为异常。SIEM系统的检测逻辑通常基于已知的异常模式,如异常IP登录、暴力破解尝试或权限提升操作,而通过合法OIDC令牌交换获得的临时凭据在日志中与正常的CI/CD操作完全一致,使得此类攻击具有极高的隐蔽性。
安全团队的应对策略
将机器身份纳入审查范围
首要行动是打破"访问审查只针对人"的思维定式。安全团队应当:
- 建立机器身份的完整清单(inventory),明确每个服务主体和联合身份的用途、权限范围和所有者
- 将这些身份纳入定期审查,识别并回收长期未使用或权限过大的身份
- 为每个身份指定明确的责任人,避免"孤儿身份"长期无人管理
在实施层面,各主要云平台已经提供了辅助工具:AWS IAM Access Analyzer可以分析角色的实际使用情况并生成最小权限策略建议;Azure AD的工作负载身份(Workload Identities)功能支持对服务主体进行条件访问策略和访问审查;GCP的Policy Analyzer则可以审计Workload Identity Federation的配置。然而,工具只是基础,真正的挑战在于将机器身份治理嵌入组织的运营流程和文化中。
把OIDC信任策略当作代码来治理
既然OIDC信任策略是真正的访问控制点,就应当以对待关键代码的严谨态度来管理它:
- 精确化条件:避免通配符,将信任条件收窄到具体的仓库、分支和环境
- 策略即代码(Policy as Code):将信任策略纳入版本控制和自动化审查,对任何变更进行同行评审
- 持续验证:使用工具定期扫描信任策略,检测过于宽松的配置和潜在的匹配漏洞
策略即代码是将安全策略、合规规则和访问控制配置以可版本化、可测试、可审计的代码形式管理的实践。在OIDC信任策略治理中,常用的工具链包括:HashiCorp Sentinel或Open Policy Agent(OPA)用于定义和执行策略规则,可以编写如"任何信任策略不得包含通配符仓库匹配"这样的自动化检查;Terraform或Pulumi等基础设施即代码工具用于声明式管理信任策略的配置,确保所有变更都通过代码仓库而非控制台手动操作;GitHub/GitLab的代码审查(Code Review)机制确保任何策略变更都经过至少一名安全团队成员的审批;而Bridgecrew/Checkov等工具则可以在CI管道中自动扫描信任策略,在配置变更进入生产之前拦截潜在风险。值得补充的是,这种工具链组合实现了"左移安全"(Shift Left Security)的理念——将安全检查从运行时前移到开发和配置阶段,使得安全缺陷在造成实际影响之前就被发现和修复。
最小权限原则在机器身份上的落地
最小权限(Least Privilege)原则同样适用于机器身份,而且执行起来可能比人类身份更有条件做到精细化。为不同的部署任务创建职责单一的身份,而非一个万能的超级角色,可以大幅缩小任何单一配置错误带来的爆炸半径。
具体而言,可以采用"一管道一身份"的策略:为构建、测试、预发布部署和生产部署分别创建独立的服务主体,每个身份只拥有完成其特定任务所需的最小权限集。例如,构建阶段的身份只需要读取源代码仓库和推送容器镜像的权限,而无需任何生产环境的访问权;生产部署身份则只需要更新特定Kubernetes命名空间或特定云资源的权限,而不是整个AWS账户的管理员权限。配合短期令牌(AWS STS临时凭据默认1小时过期)和GitHub Actions环境保护规则(要求人工审批后才能触发生产部署),可以构建出纵深防御的安全姿态。
这种"爆炸半径"(Blast Radius)思维是现代云安全架构的核心理念之一。它借鉴了物理安全中的隔舱设计——即使一个舱室被突破,损害也被限制在该舱室内部。在机器身份语境下,这意味着即使某条CI/CD管道的OIDC信任策略被利用,攻击者获得的也仅仅是该管道对应的有限权限,而非整个云环境的管理权限。结合AWS Organizations的多账户策略(将开发、预发布和生产环境隔离在不同的AWS账户中)以及Azure的管理组层级和GCP的文件夹/项目层级结构,可以在组织层面实现更彻底的权限隔离。
结语
随着自动化和CI/CD的普及,机器身份的数量正在以远超人类账户的速度增长。它们没有脸,不会登录,却常常握有系统中最致命的权限。忽视这一层面,等于在精心构筑的安全城墙上留下一扇无人看守的后门。
下一次进行安全评估时,不妨先问自己一个问题:我系统中权限最高的那个身份,是否恰恰是那个从来不会登录的? 而它背后那串OIDC信任策略字符串,你真的审查过吗?
核心要点
相关推荐

让AI审查自己的文档:验证CLAUDE.md真伪的开源工具包
RAG Techniques仓库作者开源了一套工具,用于验证AI Agent读取的CLAUDE.md和项目文档中哪些是猜测、哪些被代码证伪。文章解析其置信度标注机制、与Claude Code /init的对比及局限性。

谷歌又一AI安全研究员离职:警告"我们可能都要死"
谷歌又一位AI安全研究员离职并发出"人类可能面临灭绝"的极端警告,本文解析此类离职背后的行业张力、存在性风险争论以及AI治理的深层挑战。

19.8MB的LLM:44M参数模型如何在CPU上跑出1900 tok/s
开发者QLNI从零训练出仅19.8MB、44M参数的量化语言模型SHADOW-50M,采用三元权重和冻结指纹词表,CPU上跑出约1900 tok/s。它把计算交给专用电路、记忆交给磁盘索引,在精确计算与可靠检索任务上超越同级模型。