GitHub ActionsをIAMロールで実行する際のOIDC認証設定

# はじめに
前回記事:[GitHubActionsを用いたS3へのコンテンツデプロイ](https://qiita.com/Mouflon_127000/items/f6453ebb8c316f0cb46e)

前回の記事ではGitHub Actionsを実行する際に、Actions用IAMユーザーのアクセスキーを払い出して、
それを利用する形でAWS S3上にActionsを使ってindex.htmlをアップロードするという
GitHub Actionsワークロードの作成を行いました。

AWSのベストプラクティスとしてはアクセスキーの払い出しは極力避け、
IAMロールを利用するというのが推奨であるため、
今回はOpenID Connect連携でIAMロールを指定する方法を使って設定をします。

以下のGitHub公式ドキュメントをベースに設定を行います。

https://docs.github.com/ja/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services

## AWS側準備
### IDプロバイダ設定
最初にAWSへのIDプロバイダ追加を行います。

>プロバイダURLには https://token.actions.githubusercontent.com を指定します
「対象者」には sts.amazonaws.com を指定します。(公式のアクションを利用する場合)。

`IAM > IDプロバイダ > プロバイダを追加`から以下のパラメータを指定します。

プロバイダタイプ: OpenID Connect
プロバイダのURL: `https://token.actions.githubusercontent.com`
対象者: `sts.amazonaws.com`

![actions_2_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561546/80578431-01cb-4ae6-0677-1b9381bab131.jpeg)

### IMAロール周り
GitHub Actionsで利用するIAMロールの信頼ポリシーに以下のようなConditionを設定せよとドキュメントに記載があります。

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

今回は特定のリポジトリ内で全てのブランチでこのIAMロールを使用するため、`repo:<ユーザー名>/<リポジトリ名>:*`とブランチ指定を`*`で指定します。
信頼ポリシーの全体としては以下の内容です。
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::<AWSアカウントID>:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:<ユーザー名>/<リポジトリ名>:*"
                },
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
                }
            }
        }
    ]
}
```

## GitHub Actionsワークフロー修正
前回記事で作成した修正前のワークフローは以下の通り。

<details><summary>展開:修正前ワークフロー定義</summary><div>

```yaml:github-actions-s3upload.yml
name: Upload to S3 bucket
on:
  push:
      branches:
        - develop

env:
  SOURCE_DIR: web-contents

jobs:
  uploadjob:
    runs-on: ubuntu-latest
    steps:
      - name: checkout
        uses: actions/checkout@v4
      
      - name: list checkoutfiles
        run: | 
          pwd
          ls -al ./${{env.SOURCE_DIR}}
      
      - name: setup awscli
        uses: aws-actions/configure-aws-credentials@v4
        with: 
          aws-access-key-id: ${{ secrets.DEV_AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{vars.AWS_DEFAULT_REGION}}

      - name: deploy S3
        run: aws s3 sync ${{env.SOURCE_DIR}} s3://${{vars.DEV_AWS_S3_BUCKET}} --exact-timestamps --delete

      - name: check S3 objects
        run: aws s3 ls s3://${{vars.DEV_AWS_S3_BUCKET}} 
```
</div></details>

### 修正箇所確認
OIDCプロバイダから認証を行うために、ワークフロー内で以下のような設定をせよとドキュメントに記載があります。

```yaml
permissions:
  id-token: write # This is required for requesting the JWT
  contents: read  # This is required for actions/checkout
```

`aws-actions/configure-aws-credentials@v4`でIAMロールを利用するためには以下のように
`role-to-assume:`でGitHub Actionsで利用するIAMロールのARNを指定すればよいとの記載がありました。

```yaml
    - name: Configure AWS Credentials for China region audience
      uses: aws-actions/configure-aws-credentials@v4
      with:
        aws-region: <リージョン>
        role-to-assume: <IAMロールARN>
```

中国リージョン等デフォルトで有効ではないリージョンを利用する場合、`audience:`でstsのエンドポイントを明示的に指定してあげる必要があるそうです。

https://github.com/aws-actions/configure-aws-credentials?tab=readme-ov-file#oidc-audience

> When the JWT is created, an audience needs to be specified. Normally, you would use sts.amazonaws.com, and this action uses this by default if you don't specify one. This will work for most cases. Changing the default audience may be necessary when using non-default AWS partitions, such as China regions. You can specify the audience through the audience input:

### 修正後ワークフロー
これらを踏まえて修正したワークフロー全体は以下の通りです。
リポジトリの環境変数設定で`DEV_AWS_CICD_ROLE_ARN`にActionsで利用するIAMロールのARNを指定しています。

```diff_yaml:github-actions-s3upload.yml(修正後)
name: Upload to S3 bucket
on:
  push:
      branches:
        - develop

env:
  SOURCE_DIR: web-contents

jobs:
  uploadjob:
    runs-on: ubuntu-latest
    permissions:
+     id-token: write
+     contents: read
    steps:
      - name: checkout
        uses: actions/checkout@v4
      
      - name: list checkoutfiles
        run: | 
          pwd
          ls -al ./${{env.SOURCE_DIR}}
      
      - name: setup awscli
        uses: aws-actions/configure-aws-credentials@v4
        with: 
          aws-region: ${{vars.AWS_DEFAULT_REGION}}
-         aws-access-key-id: ${{ secrets.DEV_AWS_ACCESS_KEY_ID }}
-         aws-secret-access-key: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }}
+         role-to-assume: ${{secrets.DEV_AWS_CICD_ROLE_ARN}}

      - name: deploy S3
        run: aws s3 sync ${{env.SOURCE_DIR}} s3://${{vars.DEV_AWS_S3_BUCKET}} --exact-timestamps --delete

      - name: check S3 objects
        run: aws s3 ls s3://${{vars.DEV_AWS_S3_BUCKET}} 
```

## 動作確認
前回同様、index.htmlを変更してリポジトリにpushし、ページ上の表示が変わったことを確認します。

```diff_html
- <p>Actionsワークフローテストページ</p>
+ <p>Actionsワークフローテストページ(IAMロール)</p>
```

Actionsタブから実行履歴を確認します。

![actions_2_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561546/d198f25e-c923-e74d-4a5f-188c787aa927.jpeg)

![actions_2_03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561546/9a6eb35c-85b9-efb3-c830-3acaf06a1b59.jpeg)


Webページの確認

![actions_2_04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561546/063b09e1-dfa2-6b96-5289-67fc2095b901.jpeg)

以上。

# 参考&あわせて読みたい記事
- OIDC認証プロセスの解説

https://qiita.com/satooshi/items/0c2f5a0e2b64a1d9a4b3