GitHub Actions から AWS への OIDC(OpenID Connect)連携を設定中、特定のリポジトリや Pull Request(PR)イベント時のみ認証エラーが発生してハマったため、原因特定の手順と解決法をまとめました。
発生した問題
GitHub Actions で aws-actions/configure-aws-credentials を使って AWS IAM ロールを引き受けようとした際、以下のエラーが発生して失敗しました。
Error: Could not assume role with OIDC: Not authorized to perform sts:AssumeRoleWithWebIdentity
原因特定(CloudTrailでのデバッグ)
GitHub Actions 側のログだけではエラーの詳細は分かりません。
原因を特定するため、AWS CloudTrail の「イベント履歴 (Event history)」 でエラーログを確認しました。
-
検索条件: イベント名 =
AssumeRoleWithWebIdentity
エラーログの「ユーザー名(実際に GitHub から届いた sub クレームの値)」を確認したところ、実行イベントやリポジトリによって送信される sub のフォーマットが異なる ことがわかりました。
実際に届いていた sub の値の違い
| 条件 | 送信された sub(Subject Claim)の例 |
|---|---|
| リポジトリ A(PR時) | repo:azamarassy@(ユーザーID)/リポジトリA@(リポジトリID):pull_request |
| リポジトリ B(PR時) | repo:azamarassy/リポジトリB:pull_request |
なぜ一部のリポジトリで @ID が付与されるのか?
GitHub の設定やセキュリティ強化オプションにより、リポジトリ名やユーザー名の直後に ユーザーID や リポジトリID が自動挿入されることがあります。
これにより、従来の「名前ベース」で書いていた IAM の信頼関係(Trust Policy)の条件式にマッチせず、AccessDenied になっていました。
解決策
送信されてくる完全な sub を StringEquals(完全一致)で許可するように IAM ロールの信頼関係(Trust Policy)を書き換えます。
修正後の IAM 信頼関係(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": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": [
"repo:azamarassy@(ユーザーID)/リポジトリA@(リポジトリID):pull_request",
"repo:azamarassy/リポジトリB:pull_request"
]
}
}
}
]
}
これでOIDC 認証を通すことができるようになりました。
補足:プライベートリポジトリの「リポジトリ ID」確認手順
sub に挿入されるリポジトリ ID(数値)は、ブラウザの HTML ソースから確認できます。
- GitHub で対象リポジトリのトップページを開く。
- 右クリック ➔ 「ページのソースを表示」 を選択(
Cmd + Option + U/Ctrl + U)。 -
Cmd + Fでoctolytics-dimension-repository_idを検索する。
<!-- ソース内のこの部分の content の値がリポジトリIDです -->
<meta name="octolytics-dimension-repository_id" content="(リポジトリID)" />
まとめ
エラーが出たらまず CloudTrail を確認する: AssumeRoleWithWebIdentity のログを見ることで、実際に GitHub から送られてきた sub の値が特定できます。