GitHub Action PR合并部署报错sts:AssumeRoleWithWebIdentity未授权
问题:PR合并触发的GitHub Action无法通过AWS角色认证,手动触发正常
问题背景
我有两个GitHub Action工作流,除触发方式外配置完全一致:
manual-deploy:通过workflow_dispatch手动触发,运行正常deploy:在main分支的Pull Request合并完成时触发(pull_request事件类型为closed且github.event.pull_request.merged == true),执行时报错:Error: Not authorized to perform sts:AssumeRoleWithWebIdentity
怀疑是两个事件生成的OIDC Token的sub字段不同,想知道如何验证并解决该问题。
可正常运行的手动触发配置
name: manual-deploy on: workflow_dispatch: env: REACT_APP_VERSION: 0.1.0 jobs: build-and-deploy: runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: checkout code uses: actions/checkout@v3 - name: install node uses: actions/setup-node@v3 # using later versions of node breaks due to react-scripts v5.0.1 incompatible with typescript v5; # this specific node version works though with: node-version: "16.14.2" - name: install dependencies run: npm install - name: run tests run: npm run test - name: get current date id: date # pacific time = UTC-7:00 run: echo "REACT_APP_BUILD_DATE=$(date -u +'%m/%d/%Y %H:%M:%SPT' -d '7 hours ago')" >> $GITHUB_ENV - name: build project run: npm run build - name: configure AWS credentials uses: aws-actions/configure-aws-credentials@v2 with: role-to-assume: ${{ SECRETS.AWS_GITHUB_ROLE }} aws-region: us-west-2 - name: deploy to S3 bucket run: aws s3 sync ./build/ s3://myProject --delete - name: invalidate cloudfront cache run: aws cloudfront create-invalidation --distribution-id ${{ SECRETS.AWS_CLOUDFRONT_DIST_ID}} --paths "/*"
无法运行的PR合并触发配置
name: deploy on: pull_request: branches: - main types: closed paths-ignore: - '.github/workflows/**' env: REACT_APP_VERSION: 0.1.0 jobs: build-and-deploy: runs-on: ubuntu-latest if: github.event.pull_request.merged == true permissions: id-token: write contents: read steps: - name: checkout code uses: actions/checkout@v3 - name: install node uses: actions/setup-node@v3 # using later versions of node breaks due to react-scripts v5.0.1 incompatible with typescript v5; # this specific node version works though with: node-version: "16.14.2" - name: install dependencies run: npm install - name: run tests run: npm run test - name: get current date id: date # pacific time = UTC-7:00 run: echo "REACT_APP_BUILD_DATE=$(date -u +'%m/%d/%Y %H:%M:%SPT' -d '7 hours ago')" >> $GITHUB_ENV - name: build project run: npm run build - name: configure AWS credentials uses: aws-actions/configure-aws-credentials@v2 with: role-to-assume: ${{ SECRETS.AWS_GITHUB_ROLE }} aws-region: us-west-2 - name: deploy to S3 bucket run: aws s3 sync ./build/ s3://myProject --delete - name: invalidate cloudfront cache run: aws cloudfront create-invalidation --distribution-id ${{ SECRETS.AWS_CLOUDFRONT_DIST_ID}} --paths "/*"
当前AWS IAM角色信任策略
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<not-sure-if-this-is-sensitive-info>:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" }, "StringLike": { "token.actions.githubusercontent.com:sub": "repo:myGitHub/myProject:ref:refs/heads/main" } } } ] }
已尝试用调试模式重新运行工作流,但未获取到有效信息。
问题原因
你的AWS IAM角色信任策略中,sub字段仅允许了repo:myGitHub/myProject:ref:refs/heads/main(对应main分支直接触发或手动触发的场景),但PR合并触发的工作流,其OIDC Token的sub字段格式为repo:myGitHub/myProject:pull_request:<PR编号>,不符合当前策略的条件校验,因此认证失败。
如何验证sub字段格式
在失败的deploy工作流中添加一个步骤,解码并打印OIDC Token的sub值:
- name: 打印OIDC Token的sub字段 run: | ID_TOKEN=$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=sts.amazonaws.com" | jq -r '.value') echo "解码后的sub字段:" echo $ID_TOKEN | cut -d. -f2 | base64 -d | jq -r '.sub'
添加后重新运行工作流,即可看到PR合并场景下实际的sub字段内容。
解决方案:更新IAM信任策略
修改角色的信任策略,同时允许手动触发和PR合并触发的sub格式:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<账户ID>:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" }, "StringLike": { "token.actions.githubusercontent.com:sub": [ "repo:myGitHub/myProject:ref:refs/heads/main", "repo:myGitHub/myProject:pull_request:*" ] } } } ] }
如果需要更宽松的配置(不推荐,存在过度授权风险),也可以用通配符覆盖所有该仓库的触发场景:
"StringLike": { "token.actions.githubusercontent.com:sub": "repo:myGitHub/myProject:*" }
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

