記事を御覧いただきありがとうございます。
株式会社アドウェイズ 技術本部 インフラストラクチャーDiv 第三ユニット インフラエンジニアの田口です。
AWS 等のクラウド環境のセキュリティに関しての仕事や、エンジニア全体の開発体験を向上させる取り組み等を行っています。
本稿では GitHub Actions から OIDC 経由で AWS の複数アカウントに Switch Role し Terraform を実行する方法についてお話しようと思います。
一口感覚の記事ですが知ってると割と幸せになれる系の記事だと思いますので是非ご覧くださいませ。
背景
皆さん IAM アクセスキーの撲滅はしていらっしゃいますか?
弊社では最近 VCS を GitLab Self-Managed から GitHub Enterprise Cloud に移行しようと動いています。
我々の部署はセキュリティ関係の推進も行いますので、 CI から AWS への接続は OIDC 使う方針に切り替えて IAM アクセスキーを減らすための調査を行いました。
今までは GitLab CI での AWS へのアクセスは IAM アクセスキーを CI/CD Variables に設定し、それを使って Switch Role するという仕組みだったのですが、下記の記事で紹介している通り、 AWS の認証情報は90日ごとにローテーションを行っています。
作業自体は簡単なんですが、使っている IAM アクセスキーが多いだけにめんどくさい結構な手間だったんですよね。
OIDC 使って IAM アクセスキー撲滅したろ!と意気揚々とワークフローを組み始めるのですが、2023年2月時点ではインターネットで調査を行っても OIDC 接続をしつつ他アカウントに Switch Role を行う方法は見つかりませんでした。
何かしら方法はあるんじゃないかなーと四苦八苦しながらベテランの大先輩と調査を行った結果、OIDC 接続のみで Switch Role することができたので筆を執りました。
同じ事をしたいけど方法がわからず断念した方、丁度こういう情報を探していた方、IAM アクセスキーを撲滅したい方等の参考になれば幸いです。
解決方法
事前準備
OIDC 接続用の IAM ロールの作成を完了させてください。OIDC 接続用 IAM ロールには Switch Role を行う権限をアタッチするのをお忘れなく。
本稿では OIDC 接続から Switch Role を行う方法のみ説明するため、OIDC ロールの作成方法については記載しません。
OIDC ロールの作成方法については以下の記事が参考になると思います。
ソースコード
OIDC 接続から Switch Role を行うためには、ワークフローファイルによる環境変数の操作と .aws/config
を作成するシェルスクリプトでスイッチロールの権限設定を適切に行う必要があります。
まずはワークフローファイルと .aws/config
を作成するシェルスクリプトをご覧ください。
# .github/workflow/OIDC_switch_role.yml name: switch role on OIDC on: - push - workflow_dispatch env: TF_WORK_DIR: "./terraform/aws" AWS_PROFILE: aws_profile jobs: run_terraform_aws: permissions: id-token: write contents: read runs-on: ubuntu-22.04 steps: - name: repository checkout uses: actions/checkout@v3 - name: AWS OIDC setting uses: aws-actions/configure-aws-credentials@v1-node16 with: role-to-assume: arn:aws:iam::000000000000:role/github_actions_OIDC_role role-session-name: github_actions_OIDC_role aws-region: ap-northeast-1 - name: setup terraform uses: hashicorp/setup-terraform@v2.0.3 with: terraform_version: 1.3.9 - name: make_aws_config run: | bash ./bash/make_aws_config.sh - name: terraform init working-directory: ${{ env.TF_WORK_DIR }} run: | unset AWS_ACCESS_KEY_ID unset AWS_SECRET_ACCESS_KEY unset AWS_SESSION_TOKEN terraform init - name: terraform plan working-directory: ${{ env.TF_WORK_DIR }} run: | unset AWS_ACCESS_KEY_ID unset AWS_SECRET_ACCESS_KEY unset AWS_SESSION_TOKEN terraform plan -out outfile - name: terraform apply working-directory: ${{ env.TF_WORK_DIR }} run: | unset AWS_ACCESS_KEY_ID unset AWS_SECRET_ACCESS_KEY unset AWS_SESSION_TOKEN terraform apply outfile
#!/usr/bin/env bash # ./bash/make_aws_config.sh mkdir ~/.aws { echo "[source_profile]" echo "aws_access_key_id = ${AWS_ACCESS_KEY_ID}" echo "aws_secret_access_key = ${AWS_SECRET_ACCESS_KEY}" echo "aws_session_token = ${AWS_SESSION_TOKEN}" echo "" } > ~/.aws/credentials { echo "[profile dist_profile]" echo "source_profile = source_profile" echo "role_arn = arn:aws:iam::000000000000:role/aws_profile" echo "output = json" echo "region = ap-northeast-1" echo "" } > ~/.aws/config
ワークフローファイルの説明
ワークフロー設定に関する部分について
name: switch role on OIDC on: - push - workflow_dispatch
この部分はワークフローの名前と実行タイミングを設定しているだけですね。
env: TF_WORK_DIR: "./terraform/aws" AWS_PROFILE: aws_profile
環境変数の設定を行う部分になります。
AWS_PROFILE
は Switch Role 先のプロファイル名を設定してください。
TF_WORK_DIR
は terraform のコードが置いてあるディレクトリを設定しているだけなので必須ではありません。
jobs: run_terraform_aws: permissions: id-token: write contents: read runs-on: ubuntu-22.04
権限設定と runner の設定です。
permissions
は configure-aws-credentials
を動作させるために必要な権限を設定しています。
runner
として何を使うかはお好みでどうぞ。
各 step について
- name: repository checkout uses: actions/checkout@v3
ソースコードのチェックアウトです。定型文レベルで使われてますね。
- name: AWS OIDC setting uses: aws-actions/configure-aws-credentials@v1-node16 with: role-to-assume: arn:aws:iam::000000000000:role/github_actions_OIDC_role role-session-name: github_actions_OIDC_role aws-region: ap-northeast-1
Switch Role 元への OIDC 接続です。
- name: setup terraform uses: hashicorp/setup-terraform@v2.0.3 with: terraform_version: 1.3.9
Terraform を使いたかったのでアクションを使ってサクッとインストールしています。
OIDC 接続の Switch Role では必須ではありません。
- name: make_aws_config run: | bash ./bash/make_aws_config.sh
今回の肝になる部分です。
シェルスクリプトの内容は先程お見せしましたがもう一度見てみましょう。
#!/usr/bin/env bash # ./bash/make_aws_config.sh mkdir ~/.aws { echo "[source_profile]" echo "aws_access_key_id = ${AWS_ACCESS_KEY_ID}" echo "aws_secret_access_key = ${AWS_SECRET_ACCESS_KEY}" echo "aws_session_token = ${AWS_SESSION_TOKEN}" echo "" } > ~/.aws/credentials { echo "[profile dist_profile]" echo "source_profile = source_profile" echo "role_arn = arn:aws:iam::000000000000:role/aws_profile" echo "output = json" echo "region = ap-northeast-1" echo "" } > ~/.aws/config
スクリプト自体は単純で ~/.aws/credentials
と ~/.aws/config
を作成して設定しているだけですね。
~/.aws/config
を作成する部分の role_arn
には Switch Role 先のプロファイルを設定してください。
~/.aws/credentials
はこのままコピーで大丈夫です。(プロファイル名だけ変えたほうが良いかも)
- name: terraform init working-directory: ${{ env.TF_WORK_DIR }} run: | unset AWS_ACCESS_KEY_ID unset AWS_SECRET_ACCESS_KEY unset AWS_SESSION_TOKEN terraform init - name: terraform plan working-directory: ${{ env.TF_WORK_DIR }} run: | unset AWS_ACCESS_KEY_ID unset AWS_SECRET_ACCESS_KEY unset AWS_SESSION_TOKEN terraform plan -out outfile - name: terraform apply working-directory: ${{ env.TF_WORK_DIR }} run: | unset AWS_ACCESS_KEY_ID unset AWS_SECRET_ACCESS_KEY unset AWS_SESSION_TOKEN terraform apply outfile
terraform init
等を行っています。
ここでは Switch Role 先の AWS アカウントに Terraform からリソースを作成することを想定しています。
Switch Role 先のアカウントに操作を行う場合、必ず AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_SESSION_TOKEN
を unset
してください。
解説
コードを見てもらったのでもうわかる方もいらっしゃるかもしれませんが、何故これで Switch Role できるのか解説します。
ざっくり言ってしまえば aws-actions/configure-aws-credentials
が設定している AWS 認証関係の環境変数を手動で unset
することで、 シェルスクリプトが作成した認証情報ファイルが AWS への接続として利用できる様になるからです。
上記のリファレンスにも記載されている通り、 AWS への接続する際の認証情報には優先順位があります。
aws-actions/configure-aws-credentials
は内部的に認証情報を環境変数で設定するため、 unset
で環境変数を削除しない限り --profile
等のコマンドラインオプション以外の認証情報よりも強くなってしまいます。
なので環境変数を認証情報ファイルにソースプロファイルとして書き出し、環境変数自体は削除してしまうことで OIDC 接続先の IAM ロールを利用しつつ Switch Role も可能になるというわけです。
わかってしまえばこれだけなんですが aws-actions/configure-aws-credentials
が何をしているのか、環境変数をどうすればソースプロファイルとして扱えるのかがよくわからず結構な時間悩んでいました。
AWS の認証関係むずかしいねんな。
ユニットの宣伝
インフラストラクチャー Div 第三ユニットは SRE, DevSecOps, セキュリティに興味のある方を募集しております。
僕はインフラ関係完全未経験で入ったのですが、やりたい仕事をアピールすれば近い仕事をさせてくれますし難易度が高そうな仕事も先輩方が手厚くサポートしてくれますのでストレスなく成長できるユニットです。
もちろん経験者の方も他ユニットのサポートやアドバイス、新しい技術の調査や検証などやりがいのある仕事ができると思います。
面白そうやんけ!と思っていただけた方は是非採用ページからご応募ください。
おわりに
いかがでしたか?(定型文)
調べるのにはかなり時間がかかったんですが、文章としてまとめると意外とシンプルでした。
この記事を見て問題解決できる方がいれば幸いです。
良ければブックマークの方も何卒〜。