概要

当ブログはAmazon CloudFrontで公開、GitHubで記事を管理する構成です。
ここでは、その際に行ったOIDC設定について説明します。

構成

  • GitHub Actions
  • GitHub OIDC Provider
  • AWS IAM Role
  • S3
  • CloudFront

AWS・GitHub設定

Amazon S3バケットの作成

ソースコードを配置します。パブリックアクセスは全てブロックで問題ありません。

Amazon CloudFrontの作成

CloudFrontでディストリビューションを作成します。色々プランがありますが、今回は無料プランにしました。
オリジンタイプを「Amazon S3」とし、オリジンに作成したS3バケットを設定します。OACでS3へアクセスします。

S3バケットポリシーの変更

作成したCloudFrontからのアクセスを許可します。

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::[bucket name]/*",
            "Condition": {
                "ArnLike": {
                    "AWS:SourceArn": "arn:aws:cloudfront::[aws id]:distribution/[distribution id]"
                }
            }
        }
    ]
}

ID プロバイダの作成

AWS IAMのID プロバイダでOpenID Connectのプロバイダを作成します。
プロバイダのURLはhttps://token.actions.githubusercontent.com、対象者はsts.amazonaws.comです。 AWS IAMのOpenID Connectプロバイダ設定画面

GitHubリポジトリの作成

GitHubのリポジトリが未作成の場合、作成しておきます。

IAMロールの作成

ここまでに作成したS3、CloudFront、GitHubリポジトリのリソースで、IAMロールを作成します。
OIDCの設定を行います。この後使うため、ARN IDをコピーしておくと良いと思います。

許可ポリシーにS3、CloudFrontを設定

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowDevBucketList",
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLocation",
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::[bucket name]"
        },
        {
            "Sid": "AllowDevBucketSync",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::[bucket name]/*"
        },
        {
            "Sid": "AllowCloudFrontInvalidation",
            "Effect": "Allow",
            "Action": [
                "cloudfront:CreateInvalidation"
            ],
            "Resource": "arn:aws:cloudfront::[aws id]:distribution/[distribution ID]"
        }
    ]
}

信頼関係にOIDCの設定

subはブランチ名まで指定すると安心です。
ここでは単に組織名、リポジトリ名、ブランチ名を指定していますが、2026年7月15日以降に作られたGitHubリポジトリでは、repo:org@id/repo@id:...形式とする必要があるようです。
id部分には、各々固有の値が入ります。idはGitHub CLI(gh)を使って取得するのが一番手軽かと思います。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::[aws 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:[github organization]/[github repository]:ref:refs/heads/[branch name]"
                }
            }
        }
    ]
}

GitHub Actionsの設定

リポジトリに.github/workflows/deploy.ymlを作成、S3へのOIDC設定を記載します。
今回はJekyllを使用しています。
また各種環境値は、GitHub ActionsのRepository Variablesに設定して参照するようにしています。
※ymlファイルの名称は任意です。

name: Deploy Dev to S3

on:
  push:
    branches:
      - dev
  workflow_dispatch:

permissions:
  contents: read
  id-token: write

concurrency:
  group: deploy-dev-s3
  cancel-in-progress: false

env:
  AWS_REGION: $
  AWS_ROLE_ARN: $
  S3_BUCKET: $
  CLOUDFRONT_DISTRIBUTION_ID: $

jobs:
  deploy:
    name: Build and Deploy
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.3"
          bundler-cache: true

      - name: Validate deployment settings
        run: |
          test -n "${AWS_REGION}" || (echo "AWS_REGION repository variable is required" && exit 1)
          test -n "${AWS_ROLE_ARN}" || (echo "DEV_AWS_ROLE_ARN repository variable is required" && exit 1)
          test -n "${S3_BUCKET}" || (echo "DEV_S3_BUCKET repository variable is required" && exit 1)
          test -n "${CLOUDFRONT_DISTRIBUTION_ID}" || (echo "DEV_CLOUDFRONT_DISTRIBUTION_ID repository variable is required" && exit 1)

      - name: Validate content
        run: bundle exec ruby scripts/validate_content.rb

      - name: Build site for dev
        run: JEKYLL_ENV=production bundle exec jekyll build --strict_front_matter --baseurl ""

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v6
        with:
          aws-region: $
          role-to-assume: $
          role-session-name: sample-deploy

      - name: Sync site to S3
        run: aws s3 sync _site/ "s3://${S3_BUCKET}/" --delete

      - name: Invalidate CloudFront
        run: |
          aws cloudfront create-invalidation \
            --distribution-id "${CLOUDFRONT_DISTRIBUTION_ID}" \
            --paths "/*"

アップロード

GitHub Actionsの設定が済んだらpushします。
Build and Deployが走り、正常終了すれば成功です。S3に反映されていると思います。

参考

  • https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-in-aws
  • https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_oidc.html
  • https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html