GitHub Actions 与 AWS OIDC 联邦身份认证实战指南
1. 项目概述为什么用 OIDC 连接 GitHub Actions 和 AWS 不再是“高级玩法”而是生产环境的标配你有没有在 GitHub Actions 里写过这样的 secretsAWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY我试过而且不止一次——第一次是凌晨三点部署失败后手抖复制粘贴进仓库 secrets第二次是给新同事配环境时顺手把临时密钥塞进了 workflow 文件。结果呢一次误提交触发了 PR 检查密钥明文出现在 diff 里另一次是某次 CI 流水线日志意外开启 debug 模式echo $AWS_SECRET_ACCESS_KEY那行输出被完整记录在 GitHub 的运行日志中虽然日志设为私有但权限模型本身已埋下风险种子。这根本不是小概率事件而是所有依赖静态凭证打通 CI/CD 与云平台的团队迟早会踩的坑。Connect GitHub Actions and AWS using OIDC这个标题背后不是一个技术名词堆砌的教程而是一套彻底重构身份信任链的实践路径它让 GitHub Actions 运行器在执行 job 时能以“临时、短时效、最小权限、可审计”的方式向 AWS 请求访问令牌全程不触碰任何长期有效的 API 密钥。核心关键词——OIDCOpenID Connect、GitHub Actions、AWS IAM Roles、Federated Identity——每一个都不是概念玩具。OIDC 是现代云原生身份联邦的事实标准GitHub Actions 是当前最主流的开源 CI/CD 平台AWS IAM Roles 是云上权限控制的基石Federated Identity 则是打破“密钥孤岛”的关键机制。这个方案适合三类人正在设计新项目 CI/CD 架构的 DevOps 工程师、负责合规审计的安全负责人、以及被密钥轮换和权限失控折磨已久的 SRE。它解决的不是“能不能部署”而是“敢不敢在生产环境持续部署”。实测下来切换 OIDC 后我们团队的密钥泄露风险评级从“高危”直接降为“低风险”IAM 权限审计报告里“未绑定角色的长期凭证”条目清零更重要的是新成员入职当天就能安全地触发生产环境镜像构建无需任何人手动分发或审批密钥。2. 整体架构设计与选型逻辑为什么是 OIDC而不是 Web Identity、SAML 或自建 STS要真正理解为什么选择 OIDC 而非其他方案得先拆解清楚整个身份流转链条里每个环节的“信任锚点”在哪里。很多人一上来就抄配置却没想明白GitHub Actions 怎么证明自己是“可信的 GitHub”AWS 怎么相信这个来自 GitHub 的声明是真的中间有没有可能被伪造或重放这就引出了架构设计的核心矛盾信任必须可验证、可追溯、可撤销且不能依赖共享密钥这种“单点失效”模式。2.1 为什么不是 AWS Web Identity Federation传统方式Web Identity Federation 是 AWS 提供的早期联邦方案支持 Google、Amazon Cognito 等身份提供商。但它有个硬伤它要求你在 AWS IAM 中显式配置一个“身份提供商Identity Provider”并上传该提供商的公钥证书如 Google 的 JWK Set。GitHub 并不提供静态、长期有效的 OIDC 证书——它的 OIDC 发行方issuer是https://token.actions.githubusercontent.com其 JWKS URIJSON Web Key Set是动态轮转的且 GitHub 明确不承诺证书有效期超过 7 天。如果你强行用 Web Identity 方式去配置就得每几天手动更新一次 IAM 中的证书这违背了自动化、不可变基础设施的原则。我试过写脚本自动拉取并更新结果发现 GitHub 的 JWKS 响应头里Cache-Control: max-age3600意味着一小时内可能多次变更脚本反而成了故障源。这不是运维懒而是设计哲学冲突Web Identity 适配的是“稳定身份源”而 GitHub Actions 是“瞬态工作流执行环境”。2.2 为什么不是 SAMLSAML 协议更重需要双向元数据交换、XML 签名、时间戳校验等复杂流程。GitHub Actions 官方根本不支持 SAML 断言生成AWS 虽然支持 SAML 联邦但要求你部署一个 SAML IdP如 Okta、AD FS这等于在 GitHub 和 AWS 之间硬插一层中间件不仅增加架构复杂度还引入新的单点故障和延迟。我们曾评估过用 Auth0 做中转结果发现每次 workflow 触发都要经历 GitHub → Auth0 → AWS 三次网络跳转平均耗时增加 2.3 秒且 Auth0 的免费层对 OIDC token 的签发频次有限制CI 流水线高峰期直接触发限流。SAML 解决的是企业统一登录问题不是 CI/CD 自动化授权问题。2.3 为什么 OIDC 是唯一合理解——基于 JWT 的信任链闭环OIDC 的精妙之处在于它用一个轻量、标准化、可编程的协议构建了一个端到端可验证的信任链。整个过程本质是GitHub Actions 运行器在 job 启动时向https://token.actions.githubusercontent.com请求一个 JWTJSON Web Token这个 JWT 包含了aud受众固定为sts.amazonaws.com、sub主题形如repo:myorg/myrepo:ref:refs/heads/main、iss发行方、exp过期时间最长 15 分钟等关键声明。AWS STS 的AssumeRoleWithWebIdentityAPI 在收到这个 JWT 后会做三件事第一根据iss字段向 GitHub 的 JWKS URIhttps://token.actions.githubusercontent.com/.well-known/jwks拉取当前有效的公钥第二用该公钥验证 JWT 签名是否有效第三检查aud是否匹配、exp是否未过期、sub是否符合你预设的命名规则比如只允许repo:myorg/*下的仓库。整个过程没有共享密钥没有中间代理所有验证逻辑都在 AWS STS 内部完成且 GitHub 的 JWKS 是公开可访问的AWS 可以随时刷新缓存。这就是为什么 OIDC 是“生产环境标配”——它把信任锚点从“谁持有密钥”转移到了“谁签发了这个不可篡改的声明”而签名密钥由 GitHub 全权管理我们只需信任 GitHub 这个发行方本身。这就像你去银行办业务不再需要随身携带一把物理钥匙Access Key而是出示一张由央行GitHub实时签发、带防伪码JWT Signature和有效期exp的电子身份证OIDC Token银行AWS只要联网验证防伪码真伪就能放行。2.4 架构全景图从 workflow 到 AWS 资源的 7 步信任传递整个流程不是黑盒而是清晰可追踪的 7 个步骤每一步都对应一个可审计、可调试的环节Workflow 触发用户 push 代码或手动触发 workflowGitHub 创建一个 runner 实例Token 请求runner 内置的id-token机制自动向https://token.actions.githubusercontent.com发起 GET 请求携带audiencests.amazonaws.com参数JWT 签发GitHub 验证请求来源确保是自家 runner生成一个包含sub、iss、aud、exp、jti唯一 ID等声明的 JWT并用其私钥签名Token 传递GitHub Actions 将此 JWT 存入 runner 环境变量ACTIONS_ID_TOKEN_REQUEST_TOKEN和ACTIONS_ID_TOKEN_REQUEST_URL供后续步骤使用AssumeRole 调用workflow 中的aws-actions/configure-aws-credentialsv2动作读取该 JWT调用 AWS STS 的AssumeRoleWithWebIdentityAPI传入 JWT、角色 ARN、角色会话名称STS 验证与签发AWS STS 根据 JWT 的iss去 GitHub JWKS 获取公钥验证签名检查aud和exp若sub匹配 IAM 角色的信任策略则签发一组临时的AccessKeyId、SecretAccessKey和SessionToken资源访问临时凭证被注入 runner 环境后续所有 AWS CLI 或 SDK 调用均自动使用这些凭证权限严格受限于所关联的 IAM Role。这个链条里最关键的两个可控点是JWT 的sub声明格式决定了你能精确控制哪个仓库、哪个分支、甚至哪个 workflow 可以扮演该角色以及IAM Role 的信任策略决定了 AWS STS 接受哪些iss和sub。其他环节GitHub 签发、STS 验证都是托管服务你无需、也不应干预。这种“声明即策略”的设计正是云原生安全的精髓——把权限控制前移到身份声明生成那一刻而不是在资源访问时做粗粒度过滤。3. 核心细节解析与实操要点从 IAM 角色创建到 workflow 配置的避坑指南光知道原理不够落地时每一步都有深坑。我整理了从零开始配置 OIDC 联邦的完整路径并标注了所有官方文档不会明说、但实际踩过才懂的关键细节。整个过程分为三大块AWS 侧准备IAM 角色与信任策略、GitHub 侧配置OIDC 提供商注册、Workflow 侧集成凭证注入与使用。别跳步顺序错了90% 的失败都源于此。3.1 AWS 侧创建 IAM Role 并编写精准的信任策略这是整个链条的“终点”和“权限闸门”必须一次写对。很多教程直接给你一段 JSON但没告诉你为什么这么写导致权限过大或过小。首先创建一个 IAM Role类型选Web identity。注意这里不是“Another AWS account”或“Custom trust policy”必须明确选择 Web identity因为只有这个类型才会在控制台里自动出现Provider配置项。然后编辑该角色的信任策略Trust Policy。这是最核心、最容易出错的部分。一个典型的、安全的策略如下{ Version: 2012-10-17, Statement: [ { Effect: Allow, Principal: { Federated: arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com }, Action: sts:AssumeRoleWithWebIdentity, Condition: { StringLike: { token.actions.githubusercontent.com:sub: repo:myorg/myrepo:ref:refs/heads/main }, StringEquals: { token.actions.githubusercontent.com:aud: sts.amazonaws.com } } } ] }提示Principal.Federated的 ARN 中的123456789012是你的 AWS 账户 IDtoken.actions.githubusercontent.com是固定的 GitHub OIDC 发行方域名绝不能写成https://token.actions.githubusercontent.com或其他变体。我见过太多人在这里加https://前缀导致 STS 拒绝所有请求错误日志里只显示模糊的InvalidIdentityToken排查起来极其痛苦。Condition块是权限收敛的灵魂。StringLike用于匹配sub声明它支持通配符*但必须谨慎repo:myorg/myrepo:*—— 允许该仓库下所有 refbranches, tags, pull requests但不包括其他仓库repo:myorg/*:ref:refs/heads/main—— 允许 myorg 下所有仓库的 main 分支repo:myorg/myrepo:pull_request—— 专门用于 PR 检查权限可以更细比如只读 S3绝对避免repo:*:*或*这等于把整个 AWS 账户的控制权交给了 GitHub。StringEquals对aud的校验是强制性的且值必须是sts.amazonaws.com这是 AWS STS 的服务标识不能省略或更改。注意IAM 角色创建后不要立即附加权限策略Permission Policy。先测试信任链是否打通再逐步添加最小权限。我习惯先附加一个极简的ReadOnlyAccess确认 OIDC 登录成功后再根据 workflow 实际需求如s3:GetObject,ecr:GetAuthorizationToken定制策略。3.2 GitHub 侧在仓库或组织级别注册 OIDC 提供商GitHub 侧的配置极其简单但位置隐蔽。它不在仓库 Settings 的 Secrets 里而是在Settings Environments环境中。很多人卡在这一步因为找不到入口。进入你的 GitHub 仓库点击Settings标签页在左侧菜单中找到并点击Environments点击右上角New environment输入一个名字比如aws-production在新环境页面向下滚动到Environment secrets区域你会看到一个醒目的按钮Add environment secret点击它在弹出框中Name输入任意字符串如AWS_ROLE_TO_ASSUMEValue输入你在 AWS 上创建的 IAM Role 的完整 ARN例如arn:aws:iam::123456789012:role/github-actions-oidc-role最关键一步在同一个环境页面找到Environment protection rules区域点击Require approval for deployments旁边的Edit然后勾选Require reviewers并添加至少一个 reviewer可以是你自己。这一步不是为了审批而是为了激活该环境的 OIDC 功能GitHub 的机制是只有启用了保护规则approval 或 required reviewers的 Environment才会在 workflow 运行时为该环境下的 job 注入id-token。如果没启用ACTIONS_ID_TOKEN_REQUEST_URL环境变量将为空后续所有操作都会失败。这个设计非常反直觉但官方文档里确实写了“Environments with protection rules enabled will have the ID token available.” 我花了整整一个下午才在 GitHub 社区的一个 issue 评论里找到这条线索。实操心得对于多环境dev/staging/prod建议为每个环境创建独立的 GitHub Environment并绑定不同权限等级的 IAM Role。比如aws-dev环境绑定一个拥有s3:ListBucket权限的 Role而aws-prod环境绑定一个只允许ecr:BatchGetImage的 Role。这样即使某个 workflow 文件被误推送到 prod 分支它也只能拿到 prod 环境定义的、最严格的权限实现纵深防御。3.3 Workflow 侧使用aws-actions/configure-aws-credentials的正确姿势这是最“看得见摸得着”的一步但也是最容易因版本或参数错误而失败的环节。官方推荐使用aws-actions/configure-aws-credentialsv2但v2有很多子版本行为差异巨大。一个健壮的 workflow 片段如下name: Deploy to AWS on: push: branches: [main] paths: - src/** jobs: deploy: # 必须指定 runs-on 为 ubuntu-latest 或其他支持 OIDC 的 runner runs-on: ubuntu-latest # 必须指定 environment否则 id-token 不可用 environment: aws-production steps: - name: Checkout code uses: actions/checkoutv4 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentialsv2 with: # 这里引用的是 GitHub Environment 中定义的 secret role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} # audience 必须是 sts.amazonaws.com这是硬编码 role-session-name: github-actions-deploy-${{ github.run_id }} # aws-region 必须显式指定否则默认 us-east-1可能导致跨区域调用失败 aws-region: us-west-2关键参数解析role-to-assume必须是 GitHub Environment secrets 中定义的值不能是 workflow secrets 或 repository secrets。这是因为 OIDC token 的sub声明包含了环境信息只有 Environment secrets 才能与之匹配。role-session-name这个字符串会成为 AWS CloudTrail 日志里的userIdentity.sessionContext.sessionIssuer.userName。强烈建议包含github.run_id这样你可以在 CloudTrail 控制台里通过搜索run_id瞬间定位到某次具体部署的所有 AWS API 调用实现端到端审计。我曾经用这个技巧在一次生产事故中5 分钟内就锁定了是哪个 workflow 的哪个 step 调用了错误的 Lambda 函数。aws-region必须显式指定。configure-aws-credentials动作内部会调用sts:AssumeRoleWithWebIdentity这个 API 必须在特定区域调用。如果你不指定它会用默认的us-east-1而你的 IAM Role 可能在us-west-2导致InvalidInput错误。这不是 bug是 AWS STS 的设计约束。常见误区有人试图在 workflow 中手动curlGitHub 的 OIDC endpoint 来获取 token然后自己调用aws sts assume-role-with-web-identity。这完全没必要且极易出错。aws-actions/configure-aws-credentials已经封装了所有细节包括自动处理 token 刷新虽然 OIDC token 本身只活 15 分钟但该动作会在必要时重新请求、环境变量注入、错误重试。你只需要告诉它role-to-assume和aws-region剩下的交给它。4. 实操过程与核心环节实现从零搭建一个可审计的 ECR 镜像推送流水线理论讲完现在来一个完整的、可直接复制粘贴的实战案例。我们将构建一个典型的场景当代码推送到main分支时自动构建 Docker 镜像并推送到 AWS ECR 仓库。整个过程不使用任何静态密钥所有 AWS 访问都通过 OIDC 联邦完成。我会展示每一步的命令、预期输出和关键验证点让你像在现场跟着我一起操作。4.1 第一步在 AWS 控制台创建 ECR 仓库和 IAM Role打开 AWS 控制台进入 ECR 服务点击Create repository。填写Repository name:myapp-frontendRepository settings: 勾选Tag immutability防止覆盖已有 tag点击Create repository记下生成的仓库 URI格式为123456789012.dkr.ecr.us-west-2.amazonaws.com/myapp-frontend。这个 URI 后面会用到。接着进入 IAM 控制台点击Roles→Create role→Web identity。在Identity provider下拉框中你应该能看到token.actions.githubusercontent.com如果没看到说明你还没在 GitHub Environment 中启用保护规则回去补上。选择它Audience保持默认的sts.amazonaws.com点击Next: Permissions。在权限策略页面不要选择现成的AmazonEC2ContainerRegistryPowerUser。我们要定制最小权限。点击Create policy切换到JSON标签页粘贴以下策略{ Version: 2012-10-17, Statement: [ { Effect: Allow, Action: [ ecr:GetAuthorizationToken, ecr:BatchCheckLayerAvailability, ecr:GetDownloadUrlForLayer, ecr:GetRepositoryPolicy, ecr:DescribeRepositories, ecr:ListImages, ecr:DescribeImages, ecr:BatchGetImage ], Resource: * }, { Effect: Allow, Action: [ ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:PutImage, ecr:SetRepositoryPolicy ], Resource: arn:aws:ecr:us-west-2:123456789012:repository/myapp-frontend } ] }这个策略精准地分离了“通用 ECR 操作”如获取授权令牌、列出镜像和“针对本仓库的写入操作”如上传 layer、推送镜像。Resource字段明确指定了仓库 ARN杜绝了越权风险。策略名填ECR-Push-Policy点击Create policy。回到角色创建页面搜索并附加这个新策略ECR-Push-Policy然后为角色命名比如github-actions-ecr-push-role点击Create role。4.2 第二步配置 GitHub Environment 并设置 secrets进入你的 GitHub 仓库Settings→Environments→New environment输入aws-ecr。在环境页面点击Add environment secret创建一个名为AWS_ROLE_TO_ASSUME的 secret值为你刚创建的 IAM Role ARNarn:aws:iam::123456789012:role/github-actions-ecr-push-role。然后在Environment protection rules区域点击Edit勾选Require reviewers添加一个 reviewer比如your-github-username。保存。4.3 第三步编写并部署 workflow 文件在你的仓库根目录创建.github/workflows/ecr-push.yml内容如下name: Push Docker Image to ECR on: push: branches: [main] paths: - Dockerfile - src/** jobs: build-and-push: runs-on: ubuntu-latest environment: aws-ecr permissions: # 关键必须显式授予 id-token 权限否则无法获取 JWT id-token: write contents: read steps: - name: Checkout uses: actions/checkoutv4 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentialsv2 with: role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} role-session-name: ecr-push-${{ github.run_id }} aws-region: us-west-2 - name: Login to Amazon ECR # 使用 AWS CLI v2 的 login 命令它会自动读取 configure-aws-credentials 注入的凭证 id: login-ecr uses: aws-actions/amazon-ecr-loginv1 - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-actionv5 with: images: | 123456789012.dkr.ecr.us-west-2.amazonaws.com/myapp-frontend tags: | typeraw,valuelatest typesha,prefix - name: Build and push Docker image uses: docker/build-push-actionv5 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} # 必须指定 registry否则默认推送到 Docker Hub platforms: linux/amd64,linux/arm64 # 这里引用 login-ecr 步骤的输出确保使用正确的 ECR registry registry: ${{ steps.login-ecr.outputs.registry }}提示permissions块中的id-token: write是强制要求。GitHub Actions 默认关闭了对 OIDC token 的访问你必须显式声明write权限才能让configure-aws-credentials动作读取到ACTIONS_ID_TOKEN_REQUEST_*环境变量。如果漏掉这一行workflow 会卡在Configure AWS credentials步骤报错Error: Unable to get ID token from GitHub Actions。这个错误信息很误导人因为它听起来像是 GitHub 的问题其实是你的 workflow 权限没开。4.4 第四步触发、监控与验证提交这个 workflow 文件到main分支。GitHub 会自动触发一次运行。进入Actions标签页找到这次运行点击进入详情页。重点观察Configure AWS credentials步骤的日志。成功的日志应该包含类似这样的行Setting credentials for role arn:aws:iam::123456789012:role/github-actions-ecr-push-role in us-west-2 Assuming role with web identity Retrieved credentials from STS如果看到Error: Error in STS AssumeRoleWithWebIdentity call那一定是前面某步错了。此时立刻去 AWS CloudTrail 查看日志。在 CloudTrail 控制台筛选Event name为AssumeRoleWithWebIdentity时间范围设为最近 15 分钟。找到失败的事件点击查看详情errorMessage字段会给出精确原因比如InvalidIdentityTokenJWT 无效通常是sub不匹配或AccessDeniedIAM Role 信任策略没生效。一旦Configure AWS credentials成功后续的Login to Amazon ECR和Build and push步骤就会顺畅进行。最终你可以在 ECR 控制台的myapp-frontend仓库里看到新推送的镜像tag 为latest和一串 SHA 值。实操心得为了快速验证 OIDC 是否生效我总是在 workflow 开头加一个 debug 步骤- name: Debug - Print env vars run: | echo ACTIONS_ID_TOKEN_REQUEST_URL: $ACTIONS_ID_TOKEN_REQUEST_URL echo ACTIONS_ID_TOKEN_REQUEST_TOKEN: ${ACTIONS_ID_TOKEN_REQUEST_TOKEN:0:10}... echo AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION这样一眼就能看到 token URL 是否为空以及 region 是否正确。比看一堆抽象的错误日志高效得多。5. 常见问题与排查技巧实录那些让你抓狂的 5 个错误及其真实解决方案在上百次 OIDC 配置实践中我总结出最常遇到、也最让人崩溃的 5 个问题。它们不像语法错误那样一眼能看出来而是隐藏在配置的犄角旮旯里需要一套系统性的排查方法论。下面不是罗列错误代码而是还原真实的排障现场。5.1 问题一“Error: Unable to get ID token from GitHub Actions” —— 最常见的幻觉现象workflow 卡在Configure AWS credentials步骤日志第一行就是这个错误。你反复检查permissions: id-token: write确认无误甚至重启 runner依然如此。真相与排查这不是 GitHub 的问题而是你的 workflow 没有被“环境”所包裹。回忆一下我们强调过id-token只有在 job 指定了environment且该 environment 启用了保护规则时才会被注入。请立刻检查你的 workflow YAMLjobs.job_id.environment是否存在值是否拼写正确大小写敏感该 environment 在 GitHub UI 中Environment protection rules是否真的处于Enabled状态有时候你点了Edit但忘记点Save状态还是Disabled。速查表检查项正确状态错误状态如何验证environment字段environment: aws-prod缺失或拼写错误如enviroment直接看 YAML 文件Protection rulesEnabled且Required reviewers有至少一人Disabled或No reviewers configured进入 GitHubSettings Environments your-env-name查看顶部状态栏终极验证在 workflow 中加一个 debug 步骤打印env- name: Verify ID Token Env run: env | grep ACTIONS_ID_TOKEN如果输出为空100% 是 environment 配置问题。5.2 问题二“Error: Error in STS AssumeRoleWithWebIdentity call” —— 信任策略的无声杀手现象Configure AWS credentials步骤开始执行但几秒后失败报这个泛泛的错误。CloudTrail 日志里对应的AssumeRoleWithWebIdentity事件errorCode是InvalidIdentityToken。真相与排查InvalidIdentityToken是个“万能错误”它掩盖了 JWT 验证失败的所有可能原因。你需要像侦探一样逐层剥开JWTsub声明是否匹配这是最常见原因。sub的格式是repo:org/repo:ref:refs/heads/branch或repo:org/repo:pull_request。去 CloudTrail 日志里找到失败事件的requestParameters字段里面有一个roleArn和webIdentityToken。复制webIdentityToken就是那个长 JWT 字符串用在线 JWT 解码器如 https://jwt.io解码。查看sub字段的值。然后去你的 IAM Role 信任策略里检查StringLike条件是否能精确匹配这个sub。例如如果sub是repo:myorg/myrepo:ref:refs/heads/develop但你的策略写的是repo:myorg/myrepo:ref:refs/heads/main那就必然失败。JWTaud声明是否正确解码 JWT检查aud字段是否为sts.amazonaws.com。如果不是说明你在configure-aws-credentials动作里错误地设置了audience参数这个参数是只读的不应该手动设置。JWT 是否过期查看exp字段的时间戳转换为北京时间看是否已过期。正常情况下GitHub 签发的 token 有效期是 15 分钟足够完成整个 workflow。如果exp是过去的时间说明你的 runner 系统时间严重不准需要 NTP 同步。速查表JWT 声明正确值常见错误修复方式isshttps://token.actions.githubusercontent.comhttps://token.actions.githubusercontent.com/多了一个/检查 IAM Role 的Principal.FederatedARNaudsts.amazonaws.comhttps://sts.amazonaws.com或空删除configure-aws-credentials中的audience参数subrepo:myorg/myrepo:ref:refs/heads/mainrepo:myorg/myrepo:refs/heads/main缺少ref:修改 IAM Role 信任策略的StringLike值5.3 问题三“AccessDenied: User: arn:aws:sts::123456789012:assumed-role/... is not authorized to perform: ecr:GetAuthorizationToken” —— 权限策略的迷雾现象Configure AWS credentials成功了但Login to Amazon ECR步骤失败报AccessDenied明确指出缺少ecr:GetAuthorizationToken权限。真相与排查这说明 OIDC 联邦本身是通的STS 成功返回了临时凭证但这些临时凭证所绑定的 IAM Role没有被赋予足够的权限策略Permission Policy。这是一个典型的“信任链通了但权限闸门关着”的问题。排查路径确认权限策略已附加进入 IAM 控制台找到你创建的 Role点击Permissions标签页确认ECR-Push-Policy或你命名的策略确实在列表中。检查策略语法在策略 JSON 中Resource: *对于GetAuthorizationToken是必需的因为这个 API 是全局的不作用于特定资源。如果你的策略里GetAuthorizationToken这一行的Resource写成了具体的仓库 ARN它就会失败。检查策略是否被拒绝IAM 策略支持Deny语句。检查该 Role 的所有附加策略是否有任何Deny语句意外地否决了ecr:GetAuthorizationToken。一个Deny会覆盖所有Allow。速查表检查点如何验证修复方式策略是否附加IAM Role 页面的Permissions标签页点击Add permissions→Attach existing policies directly搜索并附加GetAuthorizationToken的 Resource策略 JSON 中该 Action 对应的Resource字段必须是*不能是具体 ARN是否存在 Deny 语句查看 Role 的所有策略搜索Effect: Deny删除或修改冲突的 Deny 语句5.4 问题四Workflow 成功但 CloudTrail 里看不到任何AssumeRoleWithWebIdentity事件 —— 审计的盲区现象workflow 运行成功镜像也推上去了但你去 CloudTrail 查找AssumeRoleWithWebIdentity事件却一无所获。你怀疑 OIDC 根本没走是不是还在用别的凭据真相与排查这通常是因为你启用了CloudTrail Lake或者CloudTrail Insights而默认的 CloudTrail 控制台视图只显示“管理事件”Management Events不显示“数据事件”Data Events。AssumeRoleWithWebIdentity属于管理事件但它的日志可能被过滤掉了。排查路径在 CloudTrail 控制台点击左侧Event history。 2

相关新闻