[小ネタ][GitHubActions]PullRequestのMergeをEventにしてAWSリソースをデプロイする際に発生したエラーの対処

2022.05.25

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

どうも、IoT事業部のアベシです!

最近GitHubActionsとAWSをOIDC連携し、Pull requestのMergeをイベントにしてAWSリソースをデプロイする際にAWSの認証が通らないエラーに遭遇しました。
PullRequestがMergeされた事をEventにしてworkflowを実行する方法と併せて、エラーの対処方法をブログに残したいと思います。

前提

GitHub ActionsはAWSとOIDC連携した上でデプロイする形をとっています。
AWSとのOIDC連携の方法は下の記事がわかりやすいです。

WorkflowのEvent設定

今回はGitHub上でPull_requestがMergeされた時にWorkflowを実行したいので、以下のようにEventを設定しました。
on: pull_requestとすることで、Pull_Requestに関連するアクションをEventにできます。 更にEvent typesをon:pull_request:types:closedと記述してclosedに指定する事で、Mergeされた時にworkflowが実行されるようになります。
また、branchs:mainのようにしてブランチ名を記載すると、記載したブランチにMergeされた時にworkflowが実行されます。

on:
  pull_request:
    branches:
      - main
    types:
      - closed

上述の設定方法の公式情報は以下のリンク先から確認できます。

workflow file

今回CD処理用に作成したWorkflow fileの全体は以下となります。

.git/workflows/cd.yaml

on:
  workflow_dispatch:
  pull_request:
    branches:
      - main
    types:
      - closed

jobs:
  ci-reuse:
    uses: ./.github/workflows/ci.yaml

  cd:
    runs-on: ubuntu-latest
    needs: ci-reuse
    env:
      AWS_ROLE_ARN: ${{ secrets.AWS_OIDC_ROLE_ARN_1 }}

    permissions:
      id-token: write
      contents: read

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Assume Role
        uses: aws-actions/configure-aws-credentials@v1
        with:
          role-to-assume: ${{ env.AWS_ROLE_ARN }}
          aws-region: ap-northeast-1
      - run: npm install
      - run: npm run deploy

補足

OIDC連携で使うAssumeRoleのARNはGitHubのSecretsに登録しており、これを読み出すために以下のように記述してます。
env:AWS_ROLE_ARN: ${{ secrets.AWS_OIDC_ROLE_ARN_1 }}

workflowの実行結果(エラー発生)

Pull requestをマージするとCDのworkflowが走りました。
しかしAssume roleの過程で以下のエラーが発生しました。

Error: Not authorized to perform sts:AssumeRoleWithWebIdentity

OIDCの認証が失敗していました。

原因

Assume Roleとして使うロールのTrusted entitiesに設定するConditionが不足してました。 Workflowの実行Eventをpull requestイベントにする場合は以下の記述が必要でした。

"token.actions.githubusercontent.com:sub":"repo:{GitHub ID}/{Repository Name}:pull_request"

GitHubのOIDCプロバイダーではWorkflow実行されるごとにJson Web Token(JWT)を発行しAWS側に送ります。 AWSのIAM IDプロバイダーは受け取ったJWTの内容とIAMロールのTrusted entitiesを検証し、合致していればAWSからAccess tokenをGitHub側へ送り返して認証が完了します。

GitHub公式情報からの引用

Pull_Requestを実行Eventに指定しましたが、上述のconditionの記述が無かったためJWTの内容と差異が有り認証が通らなかったようです。

修正後のTrusted entities

Trusted entitiesのConditionに必要な記述を追加しました。

Trusted entities

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::{AWS_Account_ID}:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": [
                        "repo:Abeshi32/GitHub_Actions_practice:ref:refs/heads/*"
                        "repo:Abeshi32/GitHub_Actions_practice:pull_request" # ←追加したCondition
                    ]
                }
            }
        }
    ]
}

再度workflowを実行

Trusted entitiesを修正し、改めてMergeを試みた所、今度はAssumeroleできました!

さいごに

Workflowの実行EventによってはConditionへ明示する必要が有る事は盲点でしたので、今後他のEventを試す際は注意していこうと思います。
また、Trusted entitiesのConditiondで設定できることは他にも色々有り、特定のリポジトリやブランチからのAssume roleを許可するこ事もできます。 逆に言いますとリポジトリ指定を記述しないとどのリポジトリからもAssumeRoleできてしまう事も有るので、リポジトリ指定は必ずすべきと言えますね。