🧚‍♂️

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

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

Discussion