GitHub ActionsにてAWS_ACCESS_KEY_IDやAWS_SECRET_ACCESS_KEYを取得する

GitHub Actionsの中で立ち上げるDockerコンテナに AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKEN を渡してAWS認証を行いたいと思い調べていました。

どうやら以下のモジュールを使うことで、OIDCでWebIdentityとしてIAM RoleをAssumeできるみたいということでやってみました。

github.com

AWSにOIDC ProviderとIAM Roleの作成

定義

以下のCloudFormationでOIDC ProviderとGitHub Actionsから利用するIAMロールを作成します。以下のIAMロールには特に権限付けてないのでほぼ何もできませんので、適宜設定してください。

AWSTemplateFormatVersion: "2010-09-09"

Description: GitHub Action Federated Role

Parameters:
  GitHubOwner:
    Type: String
  GitHubRepository:
    Type: String

Resources:
  OidcProvider:
    Type: AWS::IAM::OIDCProvider
    Properties:
      ThumbprintList:
        - 6938fd4d98bab03faadb97b34396831e3780aea1
      ClientIdList:
        - sts.amazonaws.com
      Url: https://token.actions.githubusercontent.com
  FederatedRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: github-actions-assume-role
      Description: CI/CD job role used from Github Actions
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action: sts:AssumeRoleWithWebIdentity
            Condition:
              StringLike:
                token.actions.githubusercontent.com:sub:
                  - !Sub "repo:${GitHubOwner}/${GitHubRepository}:*"
            Principal:
              Federated:
                Fn::GetAtt:
                  - OidcProvider
                  - Arn
2022/04/05修正

2022/1/13にOIDCのThumbprintは変わってしまったらしいのでCfnのThumbprint修正しました。

github.blog

内容

OpenID Connect Providerは以下のようにIAMのIDプロバイダの項目として登録されます。

f:id:yomon8:20211116084406p:plain:w500

その上で作成したIAMロールの信頼関係と紐付いてきます。Githubのリポジトリに対してIAMロールを渡す形になります。リポジトリは複数登録可能です。

f:id:yomon8:20211116084709p:plain:w500

GitHub Actionsから認証情報を取得してみる

定義

以下のようなGitHub Actionsを作成します。

jobs:
  build:
    env:
      AWS_ACCOUNT_ID: 123456789012
      AWS_ROLE_NAME: github-actions-assume-role
      AWS_DEFAULT_REGION: ap-northeast-1

    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read

    steps:
      - name: Set ARN for federated IAM role
        run: |
          export AWS_ROLE_ARN=arn:aws:iam::${AWS_ACCOUNT_ID}:role/${AWS_ROLE_NAME}
          echo AWS_ROLE_ARN=$AWS_ROLE_ARN >> $GITHUB_ENV

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@master
        with:
          aws-region: ${{ env.AWS_DEFAULT_REGION }}
          role-to-assume: ${{ env.AWS_ROLE_ARN }}

      - name: Check AWS caller identity
        run: aws sts get-caller-identity

      - name: Echo AWS Credential (display the first 5 letters)
        run: |
          echo "AWS_ACCESS_KEY_ID -> ${AWS_ACCESS_KEY_ID:0:5}***"
          echo "AWS_SECRET_ACCESS_KEY -> ${AWS_SECRET_ACCESS_KEY:0:5}***"
          echo "AWS_SESSION_TOKEN -> ${AWS_SESSION_TOKEN:0:5}***"

内容

パラメータは以下の部分です。既にGiHubのリポジトリとIAM Roleとの紐付けがAWS側でされているので、GitHub側からはIAM RoleのARNが特定できる情報があればOKです。

    env:
      AWS_ACCOUNT_ID: 123456789012
      AWS_ROLE_NAME: github-actions-assume-role
      AWS_DEFAULT_REGION: ap-northeast-1

パラメーター情報を利用してARNを組み立てます。

      - name: Set ARN for federated IAM role
        run: |
          export AWS_ROLE_ARN=arn:aws:iam::${AWS_ACCOUNT_ID}:role/${AWS_ROLE_NAME}
          echo AWS_ROLE_ARN=$AWS_ROLE_ARN >> $GITHUB_ENV

configure-aws-credentialsのモジュールにIAM Roleの情報を渡すと認証が行われます。

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@master
        with:
          aws-region: ${{ env.AWS_DEFAULT_REGION }}
          role-to-assume: ${{ env.AWS_ROLE_ARN }}

認証情報は変数に格納されますので、後続ステップでは通常通り利用することが可能です。awscliのコマンドも認証された状態で利用できます。

      - name: Check AWS caller identity
        run: aws sts get-caller-identity

      - name: Echo AWS Credential (display the first 5 letters)
        run: |
          echo "AWS_ACCESS_KEY_ID -> ${AWS_ACCESS_KEY_ID:0:5}***"
          echo "AWS_SECRET_ACCESS_KEY -> ${AWS_SECRET_ACCESS_KEY:0:5}***"
          echo "AWS_SESSION_TOKEN -> ${AWS_SESSION_TOKEN:0:5}***"

実際に実行してみたところです。

f:id:yomon8:20211116085905p:plain