CloudFormation CI/CD(GitHub Actions)ハンズオン

OIDC でキーレス認証し、IaC を検証 → 変更セット → 承認 → 自動デプロイする

GitHub Actions OIDC CloudFormation 変更セット / Environments 承認 マネコン + YAML 所要時間 75〜90 分 v1.0

📋 概要

このハンズオンでは、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 を使う理由

OIDC(OpenID Connect)を使うと、GitHub Actions は実行ごとに短期の一時認証情報を AWS から取得します。長期のアクセスキーを GitHub Secrets に保存する必要がなく、漏洩リスクを大きく下げられます

🏗️ アーキテクチャ

🐙 GitHub リポジトリ(main への push)
template.yaml + .github/workflows/deploy.yml
↓ ワークフロー起動
GitHub Actions: validate ジョブ
cfn-lint でテンプレート検証
↓ OIDC で IAM ロールを引き受け(キーレス)
plan ジョブ: 変更セットを作成(プレビュー)
aws cloudformation deploy --no-execute-changeset
↓ GitHub Environments 承認(Required reviewers)
deploy ジョブ: スタックを更新
aws cloudformation deploy → S3 + DynamoDB

作成するリソース

リソース名前 / 値備考
GitHub リポジトリhandson-iacテンプレート + ワークフロー
IAM OIDC プロバイダtoken.actions.githubusercontent.comGitHub との信頼
IAM ロールhandson-iac-gha-roleActions が引き受ける
GitHub Environmentproduction承認ゲート
デプロイ対象スタックhandson-iac-stackS3 + DynamoDB

✅ 前提条件

🔧 ツールの事前セットアップ

AWS CLI・Git・Docker などのインストールと初期設定は 環境セットアップガイド にまとめています。初めての方は先にご確認ください。

📁 ステップ 1 ― リポジトリとテンプレートの準備

GitHub に handson-iac を作成し、template.yaml を置きます(CodePipeline 版と同じ内容)。

1-1. template.yaml
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 として追加します。

🔑 ステップ 2 ― IAM OIDC プロバイダの作成

2-1. ID プロバイダを追加

IAM コンソール → 「ID プロバイダ」→「プロバイダを追加」

プロバイダのタイプOpenID Connect
プロバイダの URLhttps://token.actions.githubusercontent.com
対象者(Audience)sts.amazonaws.com

「サムプリントを取得」→「プロバイダを追加」。アカウントに 1 つあれば再利用できます。

🔐 ステップ 3 ― GitHub Actions 用 IAM ロール

3-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 条件で対象を限定する

sub 条件を付けないと、別のリポジトリからもこのロールを引き受けられてしまいます。必ず repo:<org>/<repo>:* で限定してください(特定ブランチに絞るなら :ref:refs/heads/main)。

3-2. 権限とロール名

CloudFormation でスタックを操作し、S3・DynamoDB を作成できる権限を付与します(ハンズオン用。本番は最小権限を推奨)。

  • AWSCloudFormationFullAccess
  • AmazonS3FullAccess
  • AmazonDynamoDBFullAccess
ロール名handson-iac-gha-role

作成後、ロール ARN を控えます(ワークフローで使用)。

🛡️ ステップ 4 ― 承認ゲート(GitHub Environments)

4-1. Environment を作成

GitHub リポジトリ → Settings → Environments → New environment → 名前を production にして作成。

4-2. Required reviewers を設定

作成した production の設定で 「Required reviewers」を有効にし、自分(または承認者)を追加します。これにより、この環境を使う deploy ジョブは承認されるまで実行されません

ℹ️ これが「手動承認」に相当します

CodePipeline の「手動承認アクション」と同じ役割を、GitHub では Environment の保護ルールで実現します。承認前に plan ジョブで作成済みの変更セットを AWS コンソールで確認できます。

⚙️ ステップ 5 ― ワークフローの作成

リポジトリに .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 で変更セットを作るだけ(差分プレビュー)
  • deployenvironment: production により承認まで待機 → 承認後に適用
  • IAM リソースを含むテンプレートの場合は --capabilities CAPABILITY_NAMED_IAM を追加

✅ ステップ 6 ― 動作確認

6-1. push してワークフローを起動

template.yaml.github/workflows/deploy.ymlmain に push します。リポジトリの Actions タブで validate → plan → deploy の進行を確認します。

6-2. 変更セットを確認して承認

plan 完了後、deploy ジョブが 「Waiting / Review deployments」で停止します。AWS の CloudFormation コンソールで作成された変更セットの差分を確認し、GitHub 側で 「Review deployments」→「Approve and deploy」します。

6-3. 変更を加えて再実行

template.yaml に DynamoDB のタグを追加して push し、変更セットに差分が出ること・承認ゲートが再び効くことを確認します。

      Tags:
        - Key: Project
          Value: handson-iac
✅ 確認ポイント
  • アクセスキーを一切保存せず、OIDC で AWS 認証できた
  • cfn-lint 失敗時は validate で止まる
  • 承認するまで deploy ジョブが実行されない(誤適用防止)
  • CloudFormation スタックに S3・DynamoDB が作成された

🧹 クリーンアップ

⚠️ 課金停止のため必ず実施してください

以下を削除します。スタックを削除すれば S3・DynamoDB もまとめて消えます。

  1. デプロイ対象スタックを削除:CloudFormation → handson-iac-stack(S3 にオブジェクトがあれば先に空にする)
  2. IAM ロールを削除handson-iac-gha-role
  3. IAM OIDC プロバイダを削除:他で使っていなければ token.actions.githubusercontent.com を削除
  4. GitHub の Environment / リポジトリ:不要なら production 環境やリポジトリを削除
✅ クリーンアップ完了の確認
  • CloudFormation に handson-iac-stack が残っていない
  • IAM にハンズオン用のロール/OIDC プロバイダが残っていない

学習のまとめ

習得したスキル実践内容
OIDC キーレス認証アクセスキー無しで GitHub Actions から AWS へ
IaC の検証cfn-lint をワークフローに組み込み
変更セットデプロイ前に差分をプレビュー
承認ゲートGitHub Environments の Required reviewers
ℹ️ AWS ネイティブ版もあります

CodePipeline + CodeBuild + CloudFormation デプロイアクションで同じことを実装する CloudFormation CI/CD(CodePipeline)ハンズオン もどうぞ。