- 公開日
- 最終更新日
【AWS】GitHub ActionsのOIDC認証でCloudFormationを実行しS3バケットを作成してみた
この記事を共有する
目次
はじめに
AWS環境の構築を自動化したいと思い、GitHub ActionsとAWSを連携してみることにしました。
これまでGitHubを利用したことはありましたが、CloudFormationとの連携は今回が初めてです。
調べてみると、多くの記事でOIDC認証を利用した構成が紹介されていました。OIDC認証を利用すると、GitHub SecretsへAWSアクセスキーを保存する必要がなくなるため、現在の推奨構成となっています。
ただ、初見では以下のような疑問がありました。
- GitHubとAWSはどうやって認証しているの?
- OIDC認証って何?
- IAM Roleはどこで使われるの?
- なぜアクセスキーが不要になるの?
そこで今回は、GitHub ActionsからCloudFormationを実行し、S3バケットを作成する構成を実際に構築してみました。
この記事では手順だけでなく、実際に触ってみて理解できたことも紹介します。
今回やってみること
今回のゴールは、
GitHub ActionsからAWSへ接続し、CloudFormationを利用してS3バケットを作成すること
です。
構成図は以下の通りです。

作成するAWSリソースはシンプルです。
CloudFormation Stack
S3 Bucket
まずはS3バケット作成をゴールにしながら、GitHubとAWSの連携の仕組みを理解していきます。
GitHubとAWSはどうやって認証するのか
最初に疑問だったのが、
GitHub Actions
↓
AWS
がどのように接続しているのかという点でした。
以前はAWSアクセスキーを利用する方法が一般的でした。
GitHub ジョブで AWS Secrets Manager シークレットを使用する
GitHub ActionsがSecretsからアクセスキーを取得してAWSへ接続する仕組みです。
しかし現在はOIDC認証を利用する構成が推奨されています。
OIDC認証を利用すると、
GitHub Actions
│
▼
OIDC Token
│
▼
IAM Role
│
▼
AWS
という流れになります。
つまり、アクセスキーではなく、GitHubが発行する短時間だけ有効なOIDCトークンを利用してAWSのIAM Roleを引き受けることでAWSへ接続しています。
OIDC認証の流れを理解する
実際に構築してみると、認証の流れは意外とシンプルでした。

この仕組みによって、GitHub ActionsはAWSアクセスキーを保持しなくてもAWSへ接続できます。
設定前は複雑そうな印象でしたが、
GitHub ActionsがIAM Roleを安全に利用するための仕組み
と理解するとイメージしやすくなりました。
AWS側の準備
AWS側での設定を簡単に説明していきます。
詳細な手順については以下のURLをご参照ください。
OIDC Providerを作成する
まずはGitHubとAWSの信頼関係を作成します。
AWSコンソールで以下を開きます。
IAM
↓
Identity Providers
↓
プロバイダーを追加
- 設定値
Provider Type ・・・ OpenID Connect
Provider URL ・・・ https://token.actions.githubusercontent.com
Audience ・・・ sts.amazonaws.com

IAM Policyを作成する
次にCloudFormationとS3を操作するための権限を作成します。
以下の名前で作成しましたが任意の名前で構いません。
- GitHubCloudFormationDeployPolicy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudformation:*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "*"
}
]
}
今回は検証を目的としているため権限を広めに許可しています。
実運用では必要最小限の権限に絞り込むことを推奨します。

IAM Roleを作成する
GitHub Actionsから利用するIAM Roleを作成します。
以下の名前で作成し、「IAM Policyを作成する」で作成したポリシーをアタッチしました。
- GitHubCloudFormationDeployRole
OIDC認証では、このIAM RoleをGitHub Actionsが利用することになります。
Trust Policyを設定する
IAM Role作成時に以下のような信頼ポリシーを設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": ""
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:[Owner名]@[Owner ID]/[Repository名]@[Repository ID]:ref:refs/heads/[Branch名]"
}
}
}
]
}

今回は検証のため、GitHub Actionsから利用するOIDC用ロールとCloudFormationからAWSリソースを作成する実行ロールを1つにまとめています。
本番環境では、
- GitHub Actions用IAMロール
- CloudFormation実行用IAMロール
を分離し、最小権限で運用することを推奨します。
ハマったポイント
OIDCのTrust Policy設定時、従来の記事で紹介されている以下の形式では認証に失敗しました。
repo:[Owner名]/[Repository名]:ref:refs/heads/main
CloudTrailを確認したところ、実際のSubjectは以下のようにOwner IDとRepository IDを含む形式でした。
repo:[Owner名]@[Owner ID]/[Repository名]@[Repository ID]:ref:refs/heads/main
OIDC認証で
Not authorized to perform sts:AssumeRoleWithWebIdentity
が発生する場合は、CloudTrailの AssumeRoleWithWebIdentity イベントを確認すると実際のSubjectを確認できます。
今回の検証でもCloudTrailを確認することで正しい値を特定できました。
CloudFormationテンプレートを作成する
今回はS3バケット作成だけのシンプルなテンプレートを作成します。
以下のサンプルテンプレートでは、バケット名にAWSアカウントIDを付与しています。
S3バケット名はグローバルで一意である必要があるため、このような方法で重複を避けることができます。
- s3-bucket.yml
AWSTemplateFormatVersion: '2010-09-09'
Resources:
TestS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub 'test-s3-bucket-${AWS::AccountId}'
かなりシンプルな内容です。
GitHub ActionsでWorkflowを作成する
次にWorkflowを作成します。
※ WorkflowのYAMLファイル名は例のため、任意に名前を設定してかまいません。
- .github/workflows/deploy.yml
name: Deploy CloudFormation
on:
push:
branches:
- main
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: <「IAM Roleを作成する」で作成したIAMロールのARN>
aws-region: ap-northeast-1
- name: Deploy Stack
run: |
aws cloudformation deploy \
--stack-name <作成したいCloudFormation Stack名> \
--template-file <ブランチのCFnファイル格納先>/<CFnテンプレート名>.yml
今回初めて知ったのですが、
permissions:
id-token: write
がOIDC認証には必須です。
この設定によってGitHub ActionsがOIDCトークンを取得できるようになります。
また、
uses: aws-actions/configure-aws-credentials@v6
はAWS認証用Actionで、OIDCトークンを利用してAWS IAM Roleを引き受ける処理を行ってくれます。
※ Windows Self-hosted Runnerを利用する場合、PowerShellとBashで改行記号が異なるためサンプルをそのまま利用できない場合があります。
実際に動かしてみた
設定後にGitHubへPushすると、
GitHub Actions
│
▼
IAM Role
│
▼
CloudFormation
│
▼
S3 Bucket
という流れで無事にS3バケットを作成できました。



OIDC認証という言葉だけを見ると難しそうな印象がありましたが、実際に構築してみると想像以上にシンプルな仕組みでした。
やってみて学んだこと
AWSアクセスキーが不要になる
アクセスキーを管理しなくてよいのは想像以上に楽でした。
セキュリティ面だけでなく運用面でもメリットが大きそうです。
OIDCはIAM Roleを利用するための仕組み
最初は全く別の技術だと思っていましたが、
GitHub Actions
↓
IAM Role
↓
AWS
を安全に実現するための仕組みだと理解すると分かりやすくなりました。
CloudTrailで原因を特定できる
今回の構築で最も勉強になったのは、OIDC認証エラーの調査方法です。
認証に失敗した場合、
Not authorized to perform sts:AssumeRoleWithWebIdentity
というエラーだけでは原因が分かりませんでした。
CloudTrailの AssumeRoleWithWebIdentity イベントを確認することで、実際にGitHubから渡されているSubjectを確認でき、Trust Policyの誤りを特定できました。
OIDC周りでハマった際はCloudTrailの確認が非常に有効だと感じました。
まとめ
今回はGitHub ActionsとAWSの連携を初めて構築し、CloudFormationからS3バケットを作成してみました。
構築前は、
- OIDC認証
- IAM Role
がそれぞれ別の仕組みに見えていました。
しかし実際にやってみると、
GitHub Actions
↓
OIDC認証
↓
IAM Role
↓
AWS
を実現するための一連の仕組みであることが理解できました。
また、CloudTrailを利用したOIDCトラブルシューティングや、GitHubのSubjectクレーム形式など、実際に触ってみないと分からない学びも多くありました。
GitHubとAWSの連携をこれから試してみたい方は、まずは今回のようなシンプルなS3作成から始めてみると、OIDC認証とIAM Roleの動きを理解しやすいと思います。
この記事は私が書きました
菅野 索
記事一覧趣味:ジョギング、散歩
最近体重の増加が気になるので、ダイエット頑張ってます。