Mirai Translate TECH BLOG

株式会社みらい翻訳のテックブログ

GitHub Actions で AWS OIDC 認証&プロファイル付きで awscli を使う

こんにちは。みらい翻訳のクラウド AI 翻訳サービス MiraiTranslator 開発チーム SRE の jeff です。

MiraiTranslator はサービスを AWS に構築しており、CI の一部に Github Actions を使用しています。少し前になりますが Github Actions で OIDC(OpenID Connect)認証ができるようになりました。これまで CI で AWS 上のリソースを参照・更新するときには基本的に IAM User のクレデンシャルを Github のシークレット登録し、それを使う形で認証を得ていました。

https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#requesting-the-access-tokendocs.github.com

今回の OIDC 認証対応でクレデンシャルを管理から解放され、IAM ロールと ID プロバイダーの設定をしておけば IAM User より気軽に、また柔軟に認証することができるようになりました。

実際に OIDC 認証を試してみて簡単な tips を記事に書いていこうと思います。

AWS 側の設定

AWS の ID プロバイダ設定とそれを信頼関係に設定した IAM ロールを作成します。

ID プロバイダ

以下 terraform 形式のコードです。

resource "aws_iam_openid_connect_provider" "github_actions_oidc" {
  url             = "https://token.actions.githubusercontent.com"
  client_id_list  = [
    "sts.amazonaws.com"
  ]
  thumbprint_list = [
    "6938fd4d98bab03faadb97b34396831e3780aea1"
  ]
}

画面から作成する場合は AWS マネジメントコンソールで IAM 管理画面を開き [ID プロバイダ] → [プロバイダを追加] で以下の情報を入力して作成します。

プロバイダのタイプ: OpenID Connect
プロバイダの URL: https://token.actions.githubusercontent.com
# プロバイダの URL 入力後に [サムプリントを取得] をクリック
対象者: sts.amazonaws.com

「対象者」については 公式 action を使用する場合は sts.amazonaws.com を指定する必要があります。 こちら のように自前で OIDC 認証したい場合は https://github.com/{オーガニゼーション or ユーザー名} を指定します。両方とも設定することも可能です。

IAM ロール

以下 terraform 形式のコードです。

resource "aws_iam_role" "test-githubactions-role" {
  name               = "test-githubactions-role"
  assume_role_policy = jsonencode({
    statement {
      sid    = ""
      effect = "Allow"
      actions = [
        "sts:AssumeRoleWithWebIdentity"
      ]
      principals {
        type = "Federated"
        identifiers = [
          aws_iam_openid_connect_provider.github_actions_oidc.arn
        ]
      }
      condition {
        test     = "StringLike"
        variable = "token.actions.githubusercontent.com:sub"
        values = [
          "repo:org/repo:*"
        ]
      }
    }
  })
}

画面から作成する場合は AWS マネジメントコンソールで IAM 管理画面を開き [ロール] → [ロールを作成] で以下の情報を入力して作成します。

信頼されたエンティティの種類を選択: ウェブ ID
ID プロバイダー: token.actions.githubusercontent.com:aud
Audience: sts.amazonaws.com

画面から作成した場合は IAM ロールの信頼関係の条件に自動的に Audience が設定されてしまいます。このままだと認証時に失敗してしまうので、ロールを作成したら作成したロールの管理画面を開き [信頼関係]タブ → [信頼関係の編集] で Condition の部分を修正します。

リポジトリ全体のアクションを許可したい場合は Condition 以下を↓のようにする(org は自身のオーガニゼーション or ユーザー名、repo は許可したいリポジトリ名を設定してください)

 "Condition": {
   "StringLike": {
     "token.actions.githubusercontent.com:sub": "repo:org/repo:*"
   }
 }

特定のブランチを許可したい場合は以下のようにします(branch は認証を許可したいブランチ名を設定してください)

 "Condition": {
   "StringEquals": {
     "token.actions.githubusercontent.com:sub": "repo:org/repo:ref:refs/heads/branch"
   }
 }

Condition は指定しなくても認証は通ります。 ですが IAM ロールを使い回すのはリポジトリごとに必要最低限のポリシーを与えられなかったり、あるリポジトリのために付与したポリシーが他のリポジトリに影響して CI が上手く動かなくなったりするなど、セキュリティ的にもよろしくありませんし思わぬバグを生む可能性もあります。 そのため Condition で最低でもリポジトリを絞って1リポジトリ1ロールで運用する方が良いと考えます。

Github Actions 設定

IAM ロールを作成したら適当なポリシーをロールに設定し、 Github Actions で実際に試してみましょう。 作成した IAM ロールに S3 の Read ポリシーを付けると aws s3 lsバケットリストが取れるかと思います。

name: workflow

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - name: checkout repo
        uses: actions/checkout@v2
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: ap-northeast-1
          role-to-assume: # {IAM ロールARN を指定}
          role-session-name: ${{ github.sha }}
      - name: List s3 bucket
        run: |
          aws s3 ls

Github Actions で気にするのが IAM ロールだけなのは素晴らしいですね。

一時的な認証でプロファイル付きで awscli を使う

弊社であったケースで、一部ツールに awscli のプロファイルを指定して CI で使用しているものがあります。 OIDC 認証の場合以下のような形でプロファイル指定できるようにしました。

name: workflow

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - name: checkout repo
        uses: actions/checkout@v2
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: ap-northeast-1
          role-to-assume: # {IAM ロールARN を指定}
          role-session-name: ${{ github.sha }}
      - name: Set awscli credential
        run: |
          mkdir -p ~/.aws
          echo "[profile]" >> ~/.aws/credentials
          echo "aws_access_key_id = ${{ env.AWS_ACCESS_KEY_ID }}" >> ~/.aws/credentials
          echo "aws_secret_access_key = ${{ env.AWS_SECRET_ACCESS_KEY }}" >> ~/.aws/credentials
          echo "aws_session_token = ${{ env.AWS_SESSION_TOKEN }}" >> ~/.aws/credentials
      - name: Set awscli config
         run: |
          echo "[profile]" >> ~/.aws/config
          echo "region = ${{ env. AWS_REGION }}" >> ~/.aws/config
      - name: List s3 bucket
        run: |
          aws s3 ls --profile profile

aws-actions/configure-aws-credentials を使うと GITHUB_ENV に自動的に AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN が登録されます。しかも内部的にマスクしてくれてます。 これを awscli で参照するクレデンシャル設定ファイルに書き込みます。一時的な認証のため aws_session_token の指定も必須となります。

echo "[profile]" >> ~/.aws/credentials
echo "aws_access_key_id = ${{ env.AWS_ACCESS_KEY_ID }}" >> ~/.aws/credentials
echo "aws_secret_access_key = ${{ env.AWS_SECRET_ACCESS_KEY }}" >> ~/.aws/credentials
echo "aws_session_token = ${{ env.AWS_SESSION_TOKEN }}" >> ~/.aws/credentials

リージョンを config に設定しないとコマンド実行時にエラーになるのでこちらも忘れずに設定します(awscli 使用時に --region を指定しても良いです)。

echo "[profile]" >> ~/.aws/config
echo "region = ${{ env. AWS_REGION }}" >> ~/.aws/config

以上の設定で --profile を指定して aws コマンドを実行することができるようになります。 プロファイル名は環境に合わせて指定してください。

aws s3 ls --profile profile

おまけ

CircleCI も近々 OpenID Connet に対応するそうです。 MiraiTranslator では一部 CircleCI も使用しているため AWS を呼び出している部分は OIDC に変えて IAM ユーザークレデンシャルを撲滅したいと思います。

qiita.com

みらい翻訳ではSREを募集しています

デプロイ改善に興味がある方、その他運用改善などSREに興味がある方を募集しております。 ご興味がおありの方は下記のリンクからご応募・お問い合わせをお待ちしております。

miraitranslate.com