概要
terraform を MFA 認証有の IAM ユーザ権限で switch role しつつ実行するのに手間どったので、対応方法を記載しておきます。
実行時に使用する switch role 先の arn を aws provider や s3 backend 設定にハードコードすると簡単にできるらしいのですが、role は環境(開発/テスト/本番)依存するものなので、ハードコードしたくないですよね。
同じようなことで困っている人は世の中にそこそこいて、関連する issue がいくつか挙がっています。
その中で、terraform の開発者っぽい人が、"terraform は自動実行を意識しているので、MFA の one time password を interactive に入力するとか対応しねーんだよ!" と言っているコメントがあったので、それをヒントに workaround を調査しました。
MFA および switch role 環境の場合
事前の設定
~/.aws/config, credentials ファイルは通常通り設定済みとします。# mfa の記述をしないのがポイント
ポイントは以下です。
- source profile のアカウントへのログインには MFA が必要
- target profile のとこに MFA の設定は記述しない
[profile source]
output = json
region = ap-northeast-1
[profile target]
role_arn = <arn of role to switch>
source_profile = source
region = ap-northeast-1
# mfa の設定は記述しない
[source]
aws_access_key_id = <your access key id>
aws_secret_access_key = <your secret key>
jq コマンドをダウンロードして、path を通しておきます。
terraform 実行前に実行すること
ポイントは IAM 認証時に発行される session token を事前に取得して設定しておくことです。
# 環境変数をクリアする。環境変数に認証情報が残っていると aws cli, sdk に(意図せずに)参照されてしまう。
unset AWS_SHARED_CREDENTIALS_FILE
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN
# token を取得する
export AWS_PROFILE=source # changeme
aws sts get-session-token --serial-number <your mfa device serial number> --token-code <one time code> > tmp.token
aws_access_key_id=`cat tmp.token| jq -r ".Credentials.AccessKeyId"`
aws_secret_access_key=`cat tmp.token| jq -r ".Credentials.SecretAccessKey"`
aws_session_token=`cat tmp.token| jq -r ".Credentials.SessionToken"`
# .aws/credentials ファイルとは別に credentials ファイルを作成し、terraform 実行時に参照する。
export AWS_SHARED_CREDENTIALS_FILE=tmp.credentials # 参照する credentials ファイルを変更する。
cat << EOF > $AWS_SHARED_CREDENTIALS_FILE
[source]
aws_session_token=$aws_session_token
aws_secret_access_key=$aws_secret_access_key
aws_access_key_id=$aws_access_key_id
EOF
export AWS_SDK_LOAD_CONFIG=1 # terraform AWS provider v3.0.0 以降は default 設定なので指定不要っぽい
export AWS_PROFILE=target # changeme
後は、通常通り terraform を実行できます。
AWS_SHARED_CREDENTIALS_FILE=tmp.credentials にて、session token が記載された credential ファイルを参照するようにしています。
MFA のない switch role 環境の場合
事前の設定
~/.aws/config, credentials ファイルは通常通り設定済みとします。
terraform 実行前に実行すること
export AWS_SDK_LOAD_CONFIG=1 # terraform AWS provider v3.0.0 以降は default 設定なので指定不要っぽい
export AWS_PROFILE=target # changeme
後は、通常通り terraform を実行できます。
参考: 私が上記設定を試した terraform の構成
backend には s3 を用いています。
terraform {
required_version = ">= 0.12.26"
backend "s3" {}
}
# Configure the AWS Provider
provider "aws" {
version = ">= 2.62.0"
region = "ap-northeast-1"
}
backend.hcl は環境別に用意しています。
bucket = <dev 用の bucket 名>
key = "sample_terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
terraform 実行コマンドは以下です。
ENV="dev"
export TF_DATA_DIR=./.terraform/$ENV
terraform init -backend-config=env/${ENV}/backend.hcl
terraform apply -var="env=${ENV}"
まとめ
こういうどーでもいいことで時間を使いたくないものですよね。
誰かのお役に立てばと思います。
もっと elegant な方法をご存知の方は教えてください。