2021/10/27にGithub ActionsでOpenID Connect(以下OIDC)サポートが正式にアナウンスになりました。
元々IAM Userの機密情報(アクセスキー&シークレットキー)を使ってGithub Actionsでコンテナイメージのビルド&プッシュを行っていましたが、IAM Userの機密情報を使っていることで、万が一誤って機密情報をGithubリポジトリにプッシュしてしまうこともありえ、AWSも推奨していないので、今回OICDの仕様に則り一時的な認証情報でAWSリソースへアクセス・操作できるようにしたいと思います。
AWSでの設定
まずはGithub ActionsからOIDCでAWSにアクセスできるよう、いくらかIAMでロールなどを作成します。
AWSコンソールからポチポチして作成することもできるのですが、作成したリソースの管理のためにTerraformでAWSリソースを作成したいと思います。
以下のTerraformのtfファイルを適用すれば一気に必要なAWSリソースを作成できます。
# ----- GitHub Action -----
##########################
# IAM identity providers (Githubが提供するOIDCプロバイダをAWSに登録)
##########################
# GitHub ActionsのOIDCのIDプロパイダのthumbprintを計算するため必要
data "http" "github_actions_openid_configuration" {
  url = "https://token.actions.githubusercontent.com/.well-known/openid-configuration"
}
# GitHub ActionsのOIDCのIDプロパイダのthumbprintを計算するため必要
data "tls_certificate" "github_actions" {
  url = jsondecode(data.http.github_actions_openid_configuration.body).jwks_uri
}
resource "aws_iam_openid_connect_provider" "github_oidc" {
  url = "https://token.actions.githubusercontent.com"
  client_id_list  = ["sts.amazonaws.com"]
  # https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html
  thumbprint_list = [data.tls_certificate.github_actions.certificates[0].sha1_fingerprint]
}
##########################
# IAM Role (信頼関係を登録して一時的なAWSリソースへのアクセストークンを発行するIAMロールを作成)
##########################
data "aws_iam_policy_document" "github_actions_assume_role_policy" {
  statement {
    effect  = "Allow"
    actions = ["sts:AssumeRoleWithWebIdentity"]
    principals {
      type       = "Federated"
      identifiers = [aws_iam_openid_connect_provider.github_oidc.arn]
    }
    condition {
      test     = "StringLike"
      variable = "token.actions.githubusercontent.com:sub"
      values   = ["repo:【SampleOrg/SampleRepo(※使用環境に応じて変更して下さい)】:*"]
    }
  }
}
resource "aws_iam_role" "github_actions" {
  name               = "iam_role_for_github_actions"
  assume_role_policy = data.aws_iam_policy_document.github_actions_assume_role_policy.json
}
##########################
# IAM Policy (AWS ECRへコンテナイメージがプッシュできるよう必要な権限をポリシーとして定義)
##########################
data "aws_iam_policy_document" "github_actions_resource_role_policy" {
  statement {
    actions = [
      "ecr:BatchCheckLayerAvailability",
      "ecr:PutImage",
      "ecr:InitiateLayerUpload",
      "ecr:UploadLayerPart",
      "ecr:CompleteLayerUpload",
      "ecr:GetAuthorizationToken"
    ]
    resources = ["*"]
    effect    = "Allow"
  }
}
resource "aws_iam_policy" "github_actions" {
  name        = "iam_policy_for_github_actions"
  path        = "/"
  description = "IAM Policy for GitHub Actions"
  policy      = data.aws_iam_policy_document.github_actions_resource_role_policy.json
}
# 作成したIAMロールとIAMポリシーを関連付け
resource "aws_iam_role_policy_attachment" "github_actions" {
  role       = aws_iam_role.github_actions.name
  policy_arn = aws_iam_policy.github_actions.arn
}
# ----- GitHub Action -----
Github Actionsの設定
Github Actionsでタグをプッシュするとコンテナイメージをビルド&プッシュするワークフローを作成しました。
前提としてGithub ActionsのSecretsには
- AWS_ACCOUNT_ID:AWSのアカウントID
- AWS_ECR_REPOSITORY:コンテナイメージをプッシュするリポジトリ
を設定して下さい。
name: Build Backend
on:
  push:
    tags:
      - v*
jobs:
  backend-build:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
      actions: read
    steps:
      - uses: actions/checkout@v3
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1.6.1
        with:
          aws-region: ap-northeast-1
          role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/iam_role_for_github_actions
          role-session-name: iam_role_for_github_actions
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1.4.0
      - name: Build app and push image to AWS ECR
        env:
          AWS_ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          AWS_ECR_REPOSITORY: ${{ secrets.AWS_ECR_REPOSITORY }}
        run: |
          IMAGE_TAG=$(echo ${{ github.ref }} | sed -e "s#refs/tags/##g")
          docker build -t $AWS_ECR_REGISTRY/$AWS_ECR_REPOSITORY:$IMAGE_TAG .
          docker push $AWS_ECR_REGISTRY/$AWS_ECR_REPOSITORY:$IMAGE_TAG
最後に
上記のGithub Actionsが正常に動作したら、
- Github ActionsのSecretsからAWSの認証情報を削除
- 削除した認証情報を持つIAMユーザーを削除
を実施しましょう。
以上でよりセキュアにGitHub Actionsを利用できるようになりました。
参考
GitHub Actions が OpenID Connect をサポートし、デプロイがよりセキュアに出来るようになりました!
GitHub Actions の OpenID Connect サポートについて
GitHub ActionsからAWS利用時に永続的クレデンシャル情報を渡さないようにする
Terraform だけを使って GitHub Actions OIDC ID プロパイダの thumbprint を計算する方法