🧚‍♂️

【Github Actions】静的サイトをS3 + CloudFrontへ環境毎にデプロイする🛩️

2024/04/18に公開

🛝 実現すること

  • S3 と CloudFront で公開されている静的サイトのデプロイを Github Actions で自動化する
  • develop,production 環境に分けてデプロイする

🎣 手順

  1. Github Actions で OIDC を使用して AWS 認証を行う
    1.1. Github OIDC Provider 作成する
    1.2. Github OIDC ID プロバイダーの IAM ロールを作成する
  2. Github Secrets で環境変数を設定
  3. Github Actions の Workflow を定義

🦚Github Actions で OIDC を使用して AWS 認証を行う

OpenID Connect(以下: OIDC)を使用すると、Github Actions のワークフロー内で AWS リソースアクセス出来るようになります

🐬Github OIDC Provider 作成する

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

各項目に以下の値を入力

項目 備考
プロバイダの設定 OpenID Connect -
プロバイダの URL https://token.actions.githubusercontent.com -
対象者 sts.amazonaws.com aws official actionを使用する場合に使用

入力後に「サムプリントを取得」をクリックし「プロバイダを追加」

https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#adding-the-identity-provider-to-aws

https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html

🧊Github OIDC ID プロバイダーの IAM ロールを作成する

ロール →  ロールを作成

以下の値を入力して次へ

項目 備考
信頼されたエンティティタイプ ウェブアイデンティティ -
アイデンティティプロバイダー token.actions.githubusercontent.com -
Audience sts.amazonaws.com -
Github 組織 {Github 組織名} またはユーザー名
Github リポジトリ {Github リポジトリ名} -

カスタム信頼ポリシーを設定する場合(ウェブアイデンティティで設定済の場合スキップ)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "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のユーザー名}/{Githubリポジトリ名}:*"
        }
      }
    }
  ]
}

もし、ブランチを制限したい場合は Condition を下記のように設定します

"Condition": {
  "StringEquals": {
    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
    "token.actions.githubusercontent.com:sub": "repo:{Githubのユーザー名}/{Githubリポジトリ名}:ref:refs/heads/{ブランチ}"
  }
}

https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_oidc.html#idp_oidc_Create_GitHub

次に、許可ポリシー追加の画面になるが、インラインポリシーで追加するためスキップ

ロール名を入力し、ロールを作成

ロールの一覧から作成されたロールを選択 →  許可を追加 → インラインポリシーを作成

以下を追加して作成

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket", "s3:DeleteObject", "s3:PutObject"],
      "Resource": ["arn:aws:s3:::{バケット名}", "arn:aws:s3:::{バケット名}/*"]
    }
  ]
}

https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#configuring-the-role-and-trust-policy

https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_oidc.html#idp_oidc_Create_GitHub

🎾Github Secrets で環境変数を設定する

Github Actions で使用する際の環境変数を保管する

対象のリポジトリに移動し、Settings > Security > Actions へ移動し、
「New repository secret」をクリック

以下の値を入力し追加
アカウント ID は IAM ダッシュボードから確認出来ます

Name Secret
AWS_ACCOUNT_ID_DEV {dev 環境の AWS アカウント ID}
S3_BUCKET_DEV {dev 環境のバケット名}
AWS_ACCOUNT_ID_MAIN {production 環境の AWS アカウント ID}
S3_BUCKET_MAIN {production 環境のバケット名}

🛼Github Actions の Workflow を定義

🌱 ブランチとデプロイ

  • develop ブランチに push すると、develop 環境にデプロイされる
  • main ブランチに push すると、production 環境にデプロイされる

🪼 作成するファイル

ファイル名 役割 備考
deploy.yml デプロイ共通処理 -
deploy_develop.yml develop の環境変数 -
deploy_main.yml production の環境変数 -

deploy_develop.yml定義した環境変数をdeploy.ymlに渡し、deploy.ymlを実行する流れとなります。

🕸️ サイトの構成

.
├── .github
├── README.md
├── images
├── index.html
├── js
└── styles

🐣 成果物

deploy_develop.yml
name: deploy to develop
on:
  push:
    branches:
      - develop
    # 以下のいずれかが変更された場合に実行される
    paths:
      - "images/**"
      - "js/**"
      - "styles/**"
      - index.html

jobs:
  deploy:
    # deploy.ymlを再利用する
    uses: {Github組織(ユーザー)名}/{Githubリポジトリ名}/.github/workflows/deploy.yml@develop
    # deploy.ymlに渡す環境変数を定義
    secrets:
      AWS_ROLE_ARN: arn:aws:iam::${{secrets.AWS_ACCOUNT_ID_DEV}}:role/{作成したAWSロール名}
      AWS_S3_BUCKET: ${{ secrets.S3_BUCKET_DEV }}

deploy_main.yml
name: deploy to main
on:
  push:
    branches:
      - main
    # 以下のいずれかが変更された場合に実行される
    paths:
      - "images/**"
      - "js/**"
      - "styles/**"
      - index.html

jobs:
  deploy:
    # deploy.ymlを再利用する
    uses: {Github組織(ユーザー)名}/{Githubリポジトリ名}/.github/workflows/deploy.yml@main
    # deploy.ymlに渡す環境変数を定義
    secrets:
      AWS_ROLE_ARN: arn:aws:iam::${{secrets.AWS_ACCOUNT_ID_MAIN}}:role/{作成したAWSロール名}
      AWS_S3_BUCKET: ${{ secrets.S3_BUCKET_MAIN }}

deploy.yml
name: deploy
on:
  # 別のworkflow(deploy_develop.yml, deploy_main.yml)からの呼び出しをトリガーにする
  workflow_call:
    # 呼び出し元で定義した環境変数を受け取る
    secrets:
      AWS_ROLE_ARN:
        required: true
      AWS_S3_BUCKET:
        required: true

# 共通の環境変数
env:
  AWS_REGION: ap-northeast-1

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Checkout
        uses: actions/checkout@v3

        # 認証情報を取得しAWSにアクセス可能にする
      - name: Configure AWS credentials from IAM Role
        uses: aws-actions/configure-aws-credentials@v1
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          aws-region: ${{ env.AWS_REGION }}

        # sync: ディレクトリ内のファイルをS3のディレクトリに同期させる
        # cp: ファイルをS3のバケットにコピーする
      - name: Upload files to S3
        run: |
          aws s3 sync --delete images/ s3://${{ secrets.AWS_S3_BUCKET }}/images/
          aws s3 sync --delete js/ s3://${{ secrets.AWS_S3_BUCKET }}/js/
          aws s3 sync --delete styles/ s3://${{ secrets.AWS_S3_BUCKET }}/styles/
          aws s3 cp index.html s3://${{ secrets.AWS_S3_BUCKET }}/index.html

https://zenn.dev/toritori0318/articles/7c4505d800d2eb

https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-copy

以上です!最後までありがとうございました!🧝🧝‍♀️🧝‍♂️

Rehab Tech Blog

Discussion