GitHub Actions の OIDC 連携は、ジョブごとに GitHub が発行する短い期限のトークン(ID トークン)を AWS STS に渡し、IAM ロールの一時的な認証情報に替える仕組みです。 アクセスキーを Secrets に置かずに済みます。必要なのは次の3つです。

  1. AWS に ID プロバイダ token.actions.githubusercontent.com を作る
  2. IAM ロールを作り、信頼ポリシーで「どのリポジトリ・ブランチ・環境から入れるか」を sub 条件で絞る
  3. ワークフローに 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 のときの確かめ方

  1. ジョブに environment: があるか、イベントが pull_request かを見る(sub の形式が変わる)
  2. 組織名・リポジトリ名の大文字小文字を、信頼ポリシーと合わせる(StringEquals・StringLike は大文字小文字を区別する)
  3. リポジトリが 2026年7月15日以降の作成・改名なら、不変の形式(名前@ID)にする
  4. aud が sts.amazonaws.com か(audience 入力を変えていないか)
  5. 再利用可能ワークフローから呼んでいるなら、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、aud sts.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期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?