OIDC でキーレス認証し、IaC を検証 → 変更セット → 承認 → 自動デプロイする
このハンズオンでは、GitHub Actions だけで CloudFormation テンプレート(IaC)の CI/CD を実装します。OIDC によりアクセスキーを保存せずに AWS へ認証し、cfn-lint で検証、変更セットで差分を作成、GitHub Environments の承認を経てデプロイします。AWS ネイティブの CodePipeline 版と対になる構成です。
| 項目 | 内容 |
|---|---|
| 対象サービス | GitHub Actions、IAM(OIDC プロバイダ / ロール)、CloudFormation、S3、DynamoDB |
| 主な学習内容 | OIDC キーレス認証・cfn-lint 検証・変更セット・Environments 承認ゲート |
| 所要時間 | 75〜90 分 |
| 難易度 | ★★★☆☆(中〜上級者向け) |
| 前提知識 | CloudFormation・IAM の基礎、GitHub の基本操作 |
| 費用目安 | 約 0 USD(GitHub Actions の無料枠 + デプロイ対象は無料枠内) |
OIDC(OpenID Connect)を使うと、GitHub Actions は実行ごとに短期の一時認証情報を AWS から取得します。長期のアクセスキーを GitHub Secrets に保存する必要がなく、漏洩リスクを大きく下げられます。
| リソース | 名前 / 値 | 備考 |
|---|---|---|
| GitHub リポジトリ | handson-iac | テンプレート + ワークフロー |
| IAM OIDC プロバイダ | token.actions.githubusercontent.com | GitHub との信頼 |
| IAM ロール | handson-iac-gha-role | Actions が引き受ける |
| GitHub Environment | production | 承認ゲート |
| デプロイ対象スタック | handson-iac-stack | S3 + DynamoDB |
AWS CLI・Git・Docker などのインストールと初期設定は 環境セットアップガイド にまとめています。初めての方は先にご確認ください。
ap-northeast-1(東京) に固定することGitHub に handson-iac を作成し、template.yaml を置きます(CodePipeline 版と同じ内容)。
AWSTemplateFormatVersion: '2010-09-09'
Description: Handson IaC CI/CD sample stack (S3 + DynamoDB)
Resources:
SampleBucket:
Type: AWS::S3::Bucket
Properties:
VersioningConfiguration:
Status: Enabled
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
SampleTable:
Type: AWS::DynamoDB::Table
Properties:
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
Outputs:
BucketName:
Value: !Ref SampleBucket
TableName:
Value: !Ref SampleTable
ワークフローはステップ 5 で .github/workflows/deploy.yml として追加します。
IAM コンソール → 「ID プロバイダ」→「プロバイダを追加」。
「サムプリントを取得」→「プロバイダを追加」。アカウントに 1 つあれば再利用できます。
IAM → ロール → ロールを作成 → カスタム信頼ポリシー。<your-org> は自分の GitHub ユーザー名/Organization 名に置き換えます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<account-id>:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:<your-org>/handson-iac:*"
}
}
}
]
}
sub 条件を付けないと、別のリポジトリからもこのロールを引き受けられてしまいます。必ず repo:<org>/<repo>:* で限定してください(特定ブランチに絞るなら :ref:refs/heads/main)。
CloudFormation でスタックを操作し、S3・DynamoDB を作成できる権限を付与します(ハンズオン用。本番は最小権限を推奨)。
AWSCloudFormationFullAccessAmazonS3FullAccessAmazonDynamoDBFullAccess作成後、ロール ARN を控えます(ワークフローで使用)。
GitHub リポジトリ → Settings → Environments → New environment → 名前を production にして作成。
作成した production の設定で 「Required reviewers」を有効にし、自分(または承認者)を追加します。これにより、この環境を使う deploy ジョブは承認されるまで実行されません。
CodePipeline の「手動承認アクション」と同じ役割を、GitHub では Environment の保護ルールで実現します。承認前に plan ジョブで作成済みの変更セットを AWS コンソールで確認できます。
リポジトリに .github/workflows/deploy.yml を作成します。<account-id> は自分の AWS アカウント ID に置き換えてください。
name: Deploy CloudFormation (IaC CI/CD)
on:
push:
branches: [ main ]
permissions:
id-token: write # OIDC に必須
contents: read
env:
AWS_REGION: ap-northeast-1
STACK_NAME: handson-iac-stack
ROLE_ARN: arn:aws:iam::<account-id>:role/handson-iac-gha-role
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install cfn-lint
- run: cfn-lint template.yaml
plan:
needs: validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Create change set (preview)
run: |
aws cloudformation deploy \
--template-file template.yaml \
--stack-name "$STACK_NAME" \
--no-execute-changeset \
--no-fail-on-empty-changeset
deploy:
needs: plan
runs-on: ubuntu-latest
environment: production # ← 承認ゲート(Required reviewers)
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Deploy stack
run: |
aws cloudformation deploy \
--template-file template.yaml \
--stack-name "$STACK_NAME" \
--no-fail-on-empty-changeset
permissions: id-token: write が無いと OIDC トークンを取得できませんplan は --no-execute-changeset で変更セットを作るだけ(差分プレビュー)deploy は environment: production により承認まで待機 → 承認後に適用--capabilities CAPABILITY_NAMED_IAM を追加template.yaml と .github/workflows/deploy.yml を main に push します。リポジトリの Actions タブで validate → plan → deploy の進行を確認します。
plan 完了後、deploy ジョブが 「Waiting / Review deployments」で停止します。AWS の CloudFormation コンソールで作成された変更セットの差分を確認し、GitHub 側で 「Review deployments」→「Approve and deploy」します。
template.yaml に DynamoDB のタグを追加して push し、変更セットに差分が出ること・承認ゲートが再び効くことを確認します。
Tags:
- Key: Project
Value: handson-iac
以下を削除します。スタックを削除すれば S3・DynamoDB もまとめて消えます。
handson-iac-stack(S3 にオブジェクトがあれば先に空にする)handson-iac-gha-roletoken.actions.githubusercontent.com を削除production 環境やリポジトリを削除handson-iac-stack が残っていない| 習得したスキル | 実践内容 |
|---|---|
| OIDC キーレス認証 | アクセスキー無しで GitHub Actions から AWS へ |
| IaC の検証 | cfn-lint をワークフローに組み込み |
| 変更セット | デプロイ前に差分をプレビュー |
| 承認ゲート | GitHub Environments の Required reviewers |
CodePipeline + CodeBuild + CloudFormation デプロイアクションで同じことを実装する CloudFormation CI/CD(CodePipeline)ハンズオン もどうぞ。