- Git
GitHub ActionsからOIDCでAWSへ|IAMロールの信頼ポリシー
GitHub Actions の OIDC 連携は、ジョブごとに GitHub が発行する短い期限のトークン(ID トークン)を AWS STS に渡し、IAM ロールの一時的な認証情報に替える仕組みです。 アクセスキーを Secrets に置かずに済みます。必要なのは次の3つです。
- AWS に ID プロバイダ
token.actions.githubusercontent.comを作る - IAM ロールを作り、信頼ポリシーで「どのリポジトリ・ブランチ・環境から入れるか」を
sub条件で絞る - ワークフローに
permissions: id-token: writeを書き、aws-actions/configure-aws-credentialsでロールを引き受ける
permissions:
id-token: write # ID トークンを取るために必須
contents: read # checkout 用。permissions を書くと他の権限は none になる
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd # v6.3.0
with:
role-to-assume: arn:aws:iam::123456789012:role/gha-deploy
aws-region: ap-northeast-1
allowed-account-ids: "123456789012"
- run: aws sts get-caller-identity
| 手元で確かめたこと | 結果 |
|---|---|
| configure-aws-credentials の最新タグ | v6.3.0(2026年9月11日)= e1253824e5c10ff9df46874f81ed3ec929e19cfd。v6 タグは別のコミットを指していた |
アクションを ID トークンあり(id-token: write 相当)で実行 |
Assuming role with OIDC → 認証情報の3つの変数とリージョンの2つの変数が後続のステップに渡った |
ID トークンなし(id-token: write が無い状態)で実行 |
It looks like you might be trying to authenticate with OIDC. Did you mean to set the id-token permission? の後、Credentials could not be loaded, ... で失敗 |
allowed-account-ids に別のアカウント |
The account ID of the provided credentials does not match any of the allowed account IDs で失敗 |
| ID プロバイダとロールの作成(AWS CLI) | moto で create-open-id-connect-provider・create-role・attach-role-policy が通った |
確認環境:aws-actions/configure-aws-credentials v6.3.0 のビルド済みファイル(dist/index.js)を Node.js 22.22.2 で実行し、ID トークンの発行元は自作の小さなサーバー、STS はアクションの sts-endpoint 入力で moto 5.2.4 のサーバーモードに向けて動かしました。IAM の操作は AWS CLI 1.46.1 を moto に向けて確かめています。信頼ポリシーの評価・sub の形式・不変 sub は、AWS IAM ユーザーガイド、GitHub Docs、GitHub Changelog(2026年4月23日)、アクションの README で確かめています。タグと SHA は git ls-remote で確かめました(確認日 2026年10月13日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「GitHub ActionsからOIDCでAWSへ|IAMロールの信頼ポリシー」
しくみ:どこで何が確かめられるか
sequenceDiagram
participant J as GitHub Actions のジョブ
participant G as GitHub OIDC<br/>token.actions.githubusercontent.com
participant S as AWS STS
participant I as IAM ロールの信頼ポリシー
J->>G: ID トークンを要求(id-token: write が必要)
G-->>J: JWT(sub・aud・repository・ref・environment など)
J->>S: AssumeRoleWithWebIdentity(ロール ARN + JWT)
S->>I: 発行元・aud・sub などを条件と照合
I-->>S: 一致
S-->>J: 一時的な認証情報(既定 1時間)
安全性は、信頼ポリシーの条件で決まります。 ID トークンは誰の GitHub リポジトリでも発行できます。条件を緩くすると、他人のリポジトリのワークフローからもロールに入れてしまいます。
1. ID プロバイダを作る
aws iam create-open-id-connect-provider \
--url https://token.actions.githubusercontent.com \
--client-id-list sts.amazonaws.com
{
"OpenIDConnectProviderArn": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
}
| 項目 | 値 |
|---|---|
| プロバイダの URL | https://token.actions.githubusercontent.com |
| 対象者(Audience) | sts.amazonaws.com(アクションの audience 入力の既定値と同じ) |
| サムプリント(thumbprint) | 不要。アクションの README に「The thumbprint, if specified, will be ignored.」 |
ID プロバイダはアカウントに1つです。moto で同じ URL を2回作ると EntityAlreadyExists になりました。Terraform・CloudFormation で複数のスタックから作らないように、共通の基盤側で1回だけ作ります。
2. IAM ロールを作る:信頼ポリシー
基本形:1つのリポジトリの main ブランチだけ
{
"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:octo-org/octo-repo:ref:refs/heads/main"
}
}
}
]
}
aws iam create-role --role-name gha-deploy \
--assume-role-policy-document file://trust.json \
--max-session-duration 3600
aws iam create-policy --policy-name gha-deploy-site --policy-document file://perm.json
aws iam attach-role-policy --role-name gha-deploy \
--policy-arn arn:aws:iam::123456789012:policy/gha-deploy-site
aud と sub の両方を条件に書きます。 AWS IAM ユーザーガイドによると、GitHub の ID プロバイダを信頼するロールでは、token.actions.githubusercontent.com:sub の条件が無いか、値が *・? だけのときは、信頼ポリシーの作成・更新そのものがエラーになります。
ロールに付ける権限(許可ポリシー)は、デプロイに要る操作だけにします。静的サイトを S3 に置く例です。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DeployStaticSite",
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": "arn:aws:s3:::example-site-bucket"
},
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::example-site-bucket/*"
}
]
}
信頼ポリシーと許可ポリシーの違いは、関連記事「IAMロールとは|ユーザー・ポリシーとの違いとAssumeRole、信頼ポリシー」で扱っています。
sub の形式:イベントと environment で変わる
GitHub Docs に載っている sub の形式です。
| ジョブの状況 | sub の値 |
|---|---|
environment: を書いたジョブ |
repo:ORG/REPO:environment:ENV名 |
| pull_request で起動(environment なし) | repo:ORG/REPO:pull_request |
| ブランチへの push など(environment なし) | repo:ORG/REPO:ref:refs/heads/BRANCH |
| タグへの push(environment なし) | repo:ORG/REPO:ref:refs/tags/TAG |
environment: を書いたジョブでは、sub にブランチ名が入りません。 ref:refs/heads/main だけを許可したロールに、environment: production のジョブから入ろうとすると失敗します。environment を使うなら、条件も environment の形で書きます。
条件の書き方ごとに、どの sub が通るか
StringEquals は完全一致、StringLike は *(0文字以上の任意の文字)と ?(1文字)が使えます。* は / や : にも一致します。この規則に当てはめた表です(octo-org/octo-repo のロール)。
| ジョブの sub | ①main だけ | ②repo:octo-org/octo-repo:* |
③repo:octo-org/* |
④environment production |
|---|---|---|---|---|
| main へ push | ○ | ○ | ○ | × |
| feature/x へ push | × | ○ | ○ | × |
| v1.2.0 タグ | × | ○ | ○ | × |
| pull_request | × | ○ | ○ | × |
| environment: production | × | ○ | ○ | ○ |
| 同じ組織の別リポジトリ | × | × | ○ | × |
| 不変形式の main(下で説明) | × | × | × | × |
①:StringEquals で repo:octo-org/octo-repo:ref:refs/heads/main
④:StringEquals で repo:octo-org/octo-repo:environment:production
②の repo:ORG/REPO:* は、pull_request からも入れます。 リポジトリに書き込める人なら、PR のブランチでワークフローを書き換えて、本番用のロールで AWS を操作できます。③はさらに、組織内のすべてのリポジトリから入れます。デプロイ用のロールは①か④にし、②③は読み取りだけのロールにとどめるのが安全です。
environment で絞る(承認つきの本番デプロイ)
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:octo-org/octo-repo:environment:production"
}
}
environment の sub にはブランチが入らないので、GitHub 側の environment の設定で「どのブランチから使えるか」(Deployment branches and tags)と承認者(Required reviewers)を決めます。 AWS IAM ユーザーガイドも、environment に保護ルールを付けることを勧めています。
複数のブランチ・タグを許可する
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": [
"repo:octo-org/octo-repo:ref:refs/heads/main",
"repo:octo-org/octo-repo:ref:refs/heads/release/*",
"repo:octo-org/octo-repo:ref:refs/tags/v*"
]
}
}
条件の値を配列にすると、どれか1つに一致すれば通ります(OR)。別の条件キー同士は AND です。条件演算子の一覧は、関連記事「IAMポリシーConditionの書き方|条件演算子と条件キー一覧」で扱っています。
pull_request 用(読み取りだけのロール)
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:octo-org/octo-repo:pull_request"
}
}
PR で terraform plan や cdk diff を動かすなら、デプロイ用とは別に、読み取りだけを許可したロールを作ります。
2026年7月からの「不変 sub」
2026年7月15日以降に作ったリポジトリ(と、それ以降に名前を変えた・移したリポジトリ)では、sub に組織とリポジトリの数字の ID が入ります。 GitHub Changelog(2026年4月23日)と GitHub Docs の内容です。
# 従来の形式(名前だけ)
repo:octo-org/octo-repo:ref:refs/heads/main
# 不変の形式(名前@ID)
repo:octo-org@123456/octo-repo@789012:ref:refs/heads/main
| リポジトリ | sub の形式 |
|---|---|
| 2026年7月15日以降に作成 | 不変の形式 |
| それより前に作成 | 従来の形式(リポジトリ・組織の OIDC 設定でオプトインすると不変の形式) |
| 2026年7月15日以降に名前変更・移管 | 不変の形式 |
| GitHub Enterprise Server | 対象外 |
従来の形式で書いた信頼ポリシーに、不変の形式の sub が届くと Not authorized to perform sts:AssumeRoleWithWebIdentity で失敗します(アクションの README)。上の表で、どの条件も不変の形式に一致しないのはこのためです。@ の後ろの数字は、リポジトリの設定画面か、GitHub の OIDC 設定のプレビュー用 API で確かめられます。
切り替えの間は、2つの形式を配列で並べて、両方を許可しておく方法があります。
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": [
"repo:octo-org/octo-repo:ref:refs/heads/main",
"repo:octo-org@123456/octo-repo@789012:ref:refs/heads/main"
]
}
sub 以外の条件キー(ID で絞る)
AWS は 2026年1月に、GitHub などの ID トークンの追加のクレームを信頼ポリシーの条件に使えるようにしました。IAM ユーザーガイドに載っている GitHub 用のキーです(いずれも token.actions.githubusercontent.com: を前に付ける)。
| キー | 中身 |
|---|---|
repository_id |
リポジトリの数字の ID |
repository_owner_id |
組織(オーナー)の数字の ID |
repository |
ORG/REPO |
ref |
refs/heads/main など |
environment |
environment の名前 |
job_workflow_ref |
再利用可能ワークフローのパスと ref |
workflow |
ワークフローの名前 |
actor / actor_id |
起動したユーザー |
enterprise_id |
Enterprise の ID |
IAM ユーザーガイドは、名前(repository・actor)より、変わらない ID(repository_id・repository_owner_id・actor_id)を使うよう勧めています。 GitHub の名前は手放されると別の人が取れるためです。
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:repository_owner_id": "123456",
"token.actions.githubusercontent.com:repository_id": "789012",
"token.actions.githubusercontent.com:ref": "refs/heads/main"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:octo-org*/octo-repo*:*"
}
}
sub の条件は IAM の決まりで外せないので、この例では緩い sub と ID の条件を組み合わせています。environment のキーを条件に書いたときは、ワークフロー側で environment を指定しないと一致しません(IAM ユーザーガイド)。アクションの README は、ForAllValues: を Allow で使うと「クレームが無い・綴りが違う」ときにも真になるため避けるよう書いています。
3. ワークフローを書く
name: deploy
on:
push:
branches: [main]
workflow_dispatch:
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd # v6.3.0
with:
role-to-assume: ${{ vars.AWS_ROLE_ARN }}
aws-region: ap-northeast-1
role-session-name: gha-${{ github.run_id }}
allowed-account-ids: ${{ vars.AWS_ACCOUNT_ID }}
- run: aws sts get-caller-identity
- run: aws s3 sync ./dist s3://example-site-bucket --delete
| ポイント | 理由 |
|---|---|
id-token: write |
GitHub Docs「Without id-token: write, the OIDC JWT ID token cannot be requested.」。他のリソースへの書き込み権限は与えない |
contents: read |
permissions を書くと、書かなかった権限は none になる。checkout に要る |
| SHA で固定 | タグは付け替えられる。手元では v6 タグが v6.3.0 と別のコミットを指していた |
role-to-assume を vars に |
ロールの ARN は秘密情報ではないので Variables に置ける(Secrets でもよい) |
allowed-account-ids |
想定と違うアカウントの認証情報なら失敗させる |
role-session-name |
CloudTrail で誰の実行か追える。使える文字は [\w+=,.@-]、2〜64文字 |
permissions は、ワークフロー全体ではなく AWS を使うジョブだけに書くと、ほかのジョブに ID トークンを取らせずに済みます。
アクションの主な入力
action.yml(v6.3.0)から、OIDC でよく使う入力です。
| 入力 | 既定値 | 意味 |
|---|---|---|
role-to-assume |
- | 引き受けるロールの ARN |
aws-region |
- | リージョン |
audience |
sts.amazonaws.com |
ID トークンの aud |
role-duration-seconds |
1時間 | 認証情報の有効期間。ロールの最大セッション時間以下 |
role-session-name |
GitHubActions |
セッション名 |
allowed-account-ids |
- | 許可するアカウント ID(カンマ区切り) |
retry-max-attempts |
12 | 失敗したときの再試行の回数 |
output-credentials |
- | true で認証情報をステップの outputs にも出す |
aws-profile |
- | 指定すると ~/.aws/credentials にプロファイルとして書く |
role-chaining |
- | 今の認証情報から、さらに別のロールを引き受ける |
手元で動かしたときのログ
アクションの dist/index.js を、ID トークンを返す自作サーバーと moto の STS に向けて動かした出力です(::debug::・::add-mask:: の行は除いています)。
Assuming role with OIDC
Authenticated as assumedRoleId ARO123EXAMPLE123:deploy-12345
後続のステップには、GITHUB_ENV を通じて次の変数が渡りました。
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_SESSION_TOKEN
AWS_REGION
AWS_DEFAULT_REGION
キーとトークンの値は ::add-mask:: でログに出ないようにされていました。 ID トークン(JWT)自体もマスクの対象でした。output-credentials: true を付けると、aws-access-key-id・aws-account-id・aws-expiration・authenticated-arn などがステップの outputs にも入りました。
よくあるエラーと直し方
| エラー(原文) | 原因 | 直し方 |
|---|---|---|
It looks like you might be trying to authenticate with OIDC. Did you mean to set the id-token permission? → Credentials could not be loaded, please check your action inputs: Could not load credentials from any providers |
id-token: write が無く、ID トークンを取れない(手元で再現) |
ジョブかワークフローに permissions: id-token: write |
Could not assume role with OIDC: Not authorized to perform sts:AssumeRoleWithWebIdentity |
sub・aud が信頼ポリシーと合わない。environment の有無、PR、大文字小文字、不変 sub | 実際の sub を確かめて条件を直す(下の手順) |
Could not assume role with OIDC: No OpenIDConnect provider found in your account for https://token.actions.githubusercontent.com |
ID プロバイダが無い、または URL が違う(GitHub Enterprise の発行元など) | 正しい URL でプロバイダを作り、信頼ポリシーの Federated の ARN を合わせる |
The account ID of the provided credentials does not match any of the allowed account IDs |
allowed-account-ids と違うアカウントのロール(手元で再現) |
ロールの ARN かアカウント ID を直す |
Role session name is not valid: 'deploy/main'. Must satisfy regular expression pattern: [\w+=,.@-]* |
セッション名に / など(手元で再現) |
github.run_id など使える文字だけにする |
Credentials loaded by the SDK do not match the expected access key ID configured by the action |
ほかのステップで設定した認証情報と衝突(アクションのソースの文言) | unset-current-credentials: true か、ジョブを分ける |
Not authorized のときの確かめ方
- ジョブに
environment:があるか、イベントが pull_request かを見る(sub の形式が変わる) - 組織名・リポジトリ名の大文字小文字を、信頼ポリシーと合わせる(
StringEquals・StringLikeは大文字小文字を区別する) - リポジトリが 2026年7月15日以降の作成・改名なら、不変の形式(
名前@ID)にする audがsts.amazonaws.comか(audience入力を変えていないか)- 再利用可能ワークフローから呼んでいるなら、
id-token: writeを呼び出し元のジョブで与えているか
実際の sub は、AWS の CloudTrail の AssumeRoleWithWebIdentity のイベントや、アクションの README が案内している actions-oidc-debugger で確かめられます(README は private リポジトリでだけ使うよう書いています)。
再利用可能ワークフローから使うとき
再利用可能ワークフローの中で OIDC を使うときは、呼び出し元のジョブに id-token: write を書きます。 呼び出される側は権限を広げられないためです。ID トークンの job_workflow_ref には、呼び出された側のワークフローのパスと ref(例:octo-org/octo-automation/.github/workflows/oidc.yml@refs/heads/main)が入ります。共通のデプロイ用ワークフローからだけロールに入れたいときは、この値を条件に使います。
再利用可能ワークフローの書き方と権限の受け渡しは、関連記事「GitHub Actions再利用可能ワークフロー|compositeとの違い」で扱っています。
よくある質問
Q. アクセスキーを Secrets に置く方法と比べて、何がよいですか? A. 認証情報が既定で1時間で切れ、漏れても長く使えません。キーのローテーションも要りません。どのリポジトリ・ブランチ・環境から入れるかを AWS 側の信頼ポリシーで決められます。アクセスキーを使っていた場合は、切り替え後にキーを無効化して削除します。手順は関連記事「IAMアクセスキーの作成・確認・ローテーション手順 CLI版」で扱っています。
Q. 1時間より長いジョブはどうしますか?
A. role-duration-seconds で延ばせます。ロールの最大セッション時間(--max-session-duration、最大 12時間)以下にします。超えると STS がエラーを返します。
Q. 別のアカウントのロールに入りたいときは?
A. 1つ目のロールで入り、role-chaining: true を付けたもう1回のアクションで2つ目のロールを引き受けます。2つ目のロールの信頼ポリシーには、1つ目のロールを Principal("AWS": "arn:aws:iam::<アカウント>:role/<1つ目>")として書きます。AssumeRole の流れは、関連記事「AWS STSの使い方 一時認証情報とassume-roleの違い早見表」で扱っています。
Q. AccessDenied がデプロイの途中で出ます。 A. ロールに入れた後の AccessDenied は、信頼ポリシーではなく許可ポリシーの不足です。エラー文から足りない操作を探す方法は、関連記事「AWS AccessDeniedの原因と対処|エラー文別の切り分け表」で扱っています。
まとめ
- ID プロバイダ(
token.actions.githubusercontent.com、audsts.amazonaws.com)をアカウントに1つ。サムプリントは不要 - 信頼ポリシーは
audとsubの両方。subが無い・*だけの信頼ポリシーは IAM が受け付けない - environment のジョブは sub が
environment:名前。ブランチは environment の保護ルールで絞る repo:ORG/REPO:*は pull_request からも入れる。デプロイ用ロールには使わない- 2026年7月15日以降の作成・改名リポジトリは
repo:ORG@ID/REPO@ID:...。repository_idなどの ID の条件も使える - ワークフローは
id-token: writeとcontents: read。アクションは SHA で固定(v6.3.0=e1253824...)
参考・出典
確認日はいずれも 2026年10月13日です。
- GitHub Docs「Configuring OpenID Connect in Amazon Web Services」:https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-in-aws
- GitHub Docs「OpenID Connect reference」:https://docs.github.com/en/actions/reference/security/oidc
- GitHub Changelog「Immutable subject claims for GitHub Actions OIDC tokens」(2026-04-23):https://github.blog/changelog/2026-04-23-immutable-subject-claims-for-github-actions-oidc-tokens/
- AWS IAM User Guide「Create a role for OpenID Connect federation」:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_oidc.html
- AWS IAM User Guide「IAM and AWS STS condition context keys」:https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html
- AWS What's New「AWS STS supports validation of select identity provider specific claims」(2026年1月):https://aws.amazon.com/about-aws/whats-new/2026/01/aws-sts-supports-validation-identity-provider-claims/
- aws-actions/configure-aws-credentials v6.3.0(README・action.yml・src):https://github.com/aws-actions/configure-aws-credentials
- moto:https://github.com/getmoto/moto
- AWS re:Post「Issue with assuming role in AWS using GitHub Actions」:https://www.repost.aws/questions/QUPqSGcz54SI-CTgAJ2jlHmg/issue-with-assuming-role-in-aws-using-github-actions-not-authorized-to-perform-sts-error
- DevelopersIO「GitHub Actions の OIDC プロバイダのエラー」:https://dev.classmethod.jp/articles/github-actions-oidc-provider-error-aws-settings/
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「GitHub ActionsからOIDCでAWSへ|IAMロールの信頼ポリシー」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。