巷で話題の GitHub Actions で AWS の IAM ロールを利用する方法を簡素なコードにしてみた with Terraform
この記事は何?
巷で話題の GitHub Actions で AWS の IAM ロールを利用する方法を簡素なコードにしてみました。
AWS 側の構築は Terraform で実装しています。
ぶっちゃけ以下解説している内容はアチコチのコードを寄せ集めなので調べたらわかりますが、 Terraform 且つ短縮したコードがパッと出てこなかったので使える状態でまとめました。
時間がない人はこちらだけ見てください
GitHub Actions と AWS IAM ロールの件を3行で
github actions aws oidc
とか検索すると色々出てくるので細かいことは割愛して、3行で説明します。
- 今までは AWS 外の CI サービスで AWS API を叩く時に IAM ユーザの永続的なクレデンシャルを発行する必要があり、そのクレデンシャルが漏れたり(GitHubで公開とか、退職時とか)外部で利用されるリスクがあった
- GitHub Actions で AWS の OIDC プロバイダー経由で IAM ロールが利用できることになり、永続的なクレデンシャルの発行が不要になり、一時的なクレデンシャルの利用が可能になった
- 世界が一つ安全になった
検索してよく出てくる GitHub Actions の冗長的なコード
以下のように curl を叩いて云々。これを毎回書くのか。と思うと良いけども少し冗長だよね。
steps:
- run: sleep 5 # there's still a race condition for now
- name: Configure AWS
run: |
export AWS_ROLE_ARN=arn:aws:iam::xxxxxxxxxxxx:role/ExampleGithubRole
export AWS_WEB_IDENTITY_TOKEN_FILE=/tmp/awscreds
export AWS_DEFAULT_REGION=us-east-1
echo AWS_WEB_IDENTITY_TOKEN_FILE=$AWS_WEB_IDENTITY_TOKEN_FILE >> $GITHUB_ENV
echo AWS_ROLE_ARN=$AWS_ROLE_ARN >> $GITHUB_ENV
echo AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION >> $GITHUB_ENV
curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=sigstore" | jq -r '.value' > $AWS_WEB_IDENTITY_TOKEN_FILE
- run: aws sts get-caller-identity
aws-actions/configure-aws-credentials を利用する
aws-actions/configure-aws-credentials
を利用すれば以下のように3行程度書くだけになる。
ちなみに大きな注意点として、ブランチは master
を指定している。最新バージョンは v1
だが、v1
は 2020年2月 より更新されていない。
OIDCに対応したのは 2021年9月28日の このコミット なので、このコミットハッシュを指定するか、masterを指定すれば利用可能になる。
master を指定すると bugfix の恩恵を受けられるが、 bug が含まれることもあるので、コミットハッシュか master 指定かはお好みで。
これで冗長的なコードが減るけど、 master タグは安定しないかもだし、そもそも GitHub 側も AWS 側も公式手順等が出ているわけではないので、何とも言い難い実装だけど、まぁ簡素化されたということで。
name: Example
on:
push:
branches:
- "master"
env:
# Please change here
aws_account_id: ''
jobs:
build:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- run: sleep 5
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@master
with:
aws-region: ap-northeast-1
role-to-assume: arn:aws:iam::${{ env.aws_account_id }}:role/GitHubActions
role-session-name: GitHubActions
- run: aws sts get-caller-identity
Terraform のコード
とりあえずローカルで実行できる状態にしておきました。
全容はこちらのコードを参照してください。
こちらは必要に応じて tfstate の保存先やバージョンを指定してください。
とりあえずローカルで動かすだけなら以下で十分です。
リージョンは ap-northeast-1 になっていますが、今回作成するリソースは全てグローバルサービスなのでどこを指定しても変わりません。
terraform {
required_version = ">= 0.15"
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
provider "aws" {
# Please change here
region = "ap-northeast-1"
}
github_oidc_domain は変更しなくて良いですが、reponame は自身の値に必ず書き換えてください。
IAM ポリシーの condition でリポジトリの制限を加えます。組織名のみにすることでどのリポジトリからも実行可能にすることもできますが、権限の兼ね合いで、リポジトリまで制限することが推奨されます。また、ブランチやタグを制限することもできます。
locals {
# Please change here
github_oidc_domain = "token.actions.githubusercontent.com"
# Please change here
reponame = "shogomuranushi/github-actions-aws-oidc-sample"
}
一旦、ReadOnlyAccessを付与してますが、こちらは好きに編集してください。 sts のようにカスタムポリシーも書くこともできます。
resource "aws_iam_role_policy_attachment" "github_actions1" {
role = aws_iam_role.github_actoins.name
policy_arn = "arn:aws:iam::aws:policy/ReadOnlyAccess"
}
resource "aws_iam_role_policy" "sts" {
name = "stspolicy"
role = aws_iam_role.github_actoins.name
policy = data.aws_iam_policy_document.sts.json
}
data "aws_iam_policy_document" "sts" {
statement {
actions = ["sts:GetCallerIdentity"]
resources = ["*"]
}
}
ここに紹介している部分以外のコードは、基本的には GitHub Actions と AWS OIDC と繋ぐ部分なのであまり触らない方が無難です。
繋いでいる部分のコードの解説は他ブログを参照ください。
Discussion
非常に参考になりました。ありがとうございました!