どうも、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できてしまう事も有るので、リポジトリ指定は必ずすべきと言えますね。