GitHub ActionsでIAMロールを使ってAWSリソースにアクセスする

公式の手順にのっとってやってみる。

IDプロバイダの追加

IAMのコンソールからIDプロバイダを追加します。
プロバイダのURLに「https://token.actions.githubusercontent.com」を、対象者に「sts.amazonaws.com」を設定。

IAMロールを作成

IAMロールを作成して、作ったIDプロバイダに割り当てます。
ポリシーと名前はお好みで。

信頼ポリシーの編集

自動生成された信頼エンティティはこんな感じ。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::xxxxxxxxxx:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
                }
            }
        }
    ]
}
これだとロール名がわかればどのリポジトリからもAWSアカウントにアクセスできてしまうので制限を追加します。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::xxxxxxxxxx: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:{リポジトリオーナー名}/*"
                }
            }
        }
    ]
}
リポジトリまで含めて縛ることもできますが面倒なのでオーナー名が一致すれば許可するようにしています。
リポジトリまで縛る場合はこう書きます。
"repo:{owner_name}/{repo_name}:*"

これでAWS側の準備は完了。

GitHub ActionsワークフローでAWSにアクセスしてみる

GitHubに適当なリポジトリを切ってワークフローの定義をプッシュします。
このワークフローの場合はロールに「s3:ListBucket」権限が必要です。
name: "ci"

on: [ workflow_dispatch ]

jobs:
  ci:
    runs-on: ubuntu-latest
    permissions:
      id-token: write # 指定が必要

    steps:
      - uses: actions/checkout@v2

      - uses: aws-actions/configure-aws-credentials@v1
        with:
          role-to-assume: ${{ secrets.AWS_IAM_ROLE_ARN }} # 作成したIAMロールのARN
          role-session-name: github-actions-${{ github.run_id }} # CloudTrailイベントに表示されるユーザー名
          aws-region: ap-northeast-1

      - run: aws sts get-caller-identity

      - run: aws s3 ls
ロールはGithubのシークレットに格納しました。
プライベートリポジトリなら直接埋め込んであってもいいかもしれません。

注意点としてpermissionsを指定しているのでこのワークフロージョブはGITHUB_TOKENを使ってできる操作がid-tokenの読み書きのみに限定されてしまっています。
AWSへの操作と合わせてチェックアウトやイシューの書き込みなどを行いたい場合はちゃんと権限を追加で指定してやらないといけません。



プッシュしたらこんな感じで実行できます。
こんな感じでAssumeRoleができてS3が参照できていれば成功です。
アクセスキーを発行しなくていいぶん、よりセキュアで手間も少なく便利です。