environment設定でOIDC認証が失敗した話 (GitHub Actions)
GitHub Actions と AWS の OIDC 連携は、アクセスキーを不要にできるので非常に便利です。
これまでも同様の設定経験はありましたが、今回、特定のワークフローに限って突然認証エラーが発生し、原因の特定に時間を要しました。
原因は、GitHub Actions
で einvoroment
を使用すると sub
クレームが変更されることでした。
(ちゃんと仕様を把握せずに使っていたせいです... orz)
事象:特定の信頼ポリシーでのみ認証が失敗
信頼ポリシーの確認
リポジトリを具体的に指定した場合は失敗し、ワイルドカードを使った場合にのみ成功していました。
# 失敗する例
{
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": [
"repo:{MyOrg}/{repo}:ref:refs/heads/main",
"repo:{MyOrg}/{repo}:ref:refs/heads/feature/*"
]
}
}
}
# 成功する例
{
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:{MyOrg}/*"
}
}
}
IAM ポリシーの記述ミスや権限設定も確認しましたが、原因が掴めませんでした。
原因調査:OIDCトークンの内容確認
GitHub Actions からのサンプルログ
- GitHub ActionsのワークフローログでOIDCトークンのsubクレームを確認
OIDC Debug Information:
Repository: {MyOrg}/{repo}
Ref: refs/heads/feature/fix-deployment
SHA: a1b2c3d4e5f6789012345678901234567890abcd
Actor: developer-user
Workflow: Deploy API Service (OIDC)
Run ID: 12345678901
Event: workflow_dispatch
Expected sub claim: repo:{MyOrg}/{repo}:ref:refs/heads/feature/fix-deployment
CloudTrail からのサンプルログ
{
"eventSource": "sts.amazonaws.com",
"eventName": "AssumeRoleWithWebIdentity",
"errorCode": "AccessDenied",
"userIdentity": {
"type": "WebIdentityUser",
"userName": "repo:{MyOrg}/{repo}:environment:development"
}
}
この userName
が AWS が受け取った sub
クレームであり、
リポジトリ名+ブランチ情報ではなく environment 名 が渡されていることがわかりました。
原因:environment設定によるsubクレーム形式の変更
CloudTrail のログが示すように、ジョブに environment
を設定していると sub
クレームの形式が変わります。
environment 設定 |
sub クレームの形式 |
---|---|
なし | repo:{MyOrg}/{repo}:ref:refs/heads/branch-name |
あり | repo:{MyOrg}/{repo}:environment:environment-name |
GitHub の公式ドキュメントでもこの挙動は明記されています:
The following example OIDC token uses a subject (sub) that references a job environment named prod in the octo-org/octo-repo repository
参考:About security hardening with OpenID Connect
対処法
認証の仕組みが理解できれば、運用に合わせて使い分けができます。
パターン1: 環境ベース認証(推奨)
- 各環境で
environment
を設定 - 環境ごとに別々のIAMロールで権限を分離
# 開発用
"repo:{MyOrg}/{repo}:environment:development"
# 検証用
"repo:{MyOrg}/{repo}:environment:staging"
# 本番用
"repo:{MyOrg}/{repo}:environment:production"
パターン2: ブランチベース認証
-
environment
設定なしでブランチ名による認証 - feature/* ブランチから開発環境へのデプロイなど
"repo:{MyOrg}/{repo}:ref:refs/heads/main",
"repo:{MyOrg}/{repo}:ref:refs/heads/feature/*"
まとめ
今回の認証エラーは、environment
設定の有無によってOIDCトークンの sub
クレーム形式が変わるという、見落としがちなGitHub Actionsの仕様が原因でした。
運用パターンとしては以下のような使い分けが可能です:
-
開発環境:
environment
なし → ブランチベース認証 -
本番環境:
environment
あり → 環境ベース認証
これまであまり気にせずテンプレートで作成していたので、完全に盲点でした。
同じ問題で悩む方の参考になれば幸いです。
Discussion