はじめに
Terraform Cloud(以下TFC)では、AWSアカウントに接続する際、静的なクレデンシャル(いわゆるアクセスキー)を使わず、Dynamic Credentialを使うことで、よりセキュアな接続をすることができます。
Terraformはその性質上、高権限が必要な場合が殆どですので、なるべくアクセスキーは使いたくない・・・といった場合に活躍しますね👍
ですが1つのワークスペースから、複数AWSアカウントに対してのDynamic Credential設定に関する情報が、公式のものも含めて少なく苦戦したので、ここに書き残そうと思います。
複数のAWSアカウントに接続したいケースとして、例えば
- AアカウントとBアカウントをVPCピアリングで接続したい
- Aアカウントで構築したWebシステムのDNSレコードをBアカウントに登録したい
といったものがあると思います。
ゴール
- TFC環境にて1つのワークスペースから複数AWSアカウントに接続するためのDynamic Credentialを設定する
書かないこと
まずはシングルAWSアカウントとのDynamic Credential設定
マルチAWSアカウント接続を設定する前に、シングルAWSアカウント接続について理解しておく必要があります。
この記事に辿り着いた方の多くは、ここはすでにクリアされていることも多いでしょうし、公式のドキュメントや、紹介記事も多数ありますので詳細は割愛します。
公式ドキュメント
developer.hashicorp.com
Zenn(moaikids様)
zenn.dev
簡単に書くと、以下の設定が必要です。
- OIDC設定
- IAMロール
- TFC上にVariables(
TFC_AWS_PROVIDER_AUTH
、TFC_AWS_RUN_ROLE_ARN
)を作成
(Variable SetでもOK)
OIDCとIAMロールについては、一撃で作成できるモジュールがHashicorp公式で公開されていますので、これを使うのがオススメです。
github.com
注意事項としては、TFCでこれらOIDC、IAMロール作成を行わないことです!
TFCの動作の前提になるものなので、別で管理すべきでしょう。
VariablesについてはTFCでもOKです👍
マルチAWSアカウントとのDynamic Credentials設定
ここからが本題です。
実は上記の公式ドキュメントの一番下にシレっと書いてあるのですが、初見ではなかなか分かりづらいです。
私も色々検証したり、サポートに聞いたりしてようやく設定できました。
AWSへの設定
まず、対象となるAWSアカウント(ここではアカウントA、アカウントB、とします)のそれぞれに、シングルアカウントの時と同様にOIDC設定とIAMロール作成を行います。
ここまでは同じ。
TFCへの設定
次にVariablesですが、以下のように作成します。
アカウントA用
Variable名 |
値 |
TFC_AWS_PROVIDER_AUTH_accountA |
true |
TFC_AWS_RUN_ROLE_ARN_accountA |
作成したアカウントAのIAMロールARN 例:arn:aws:iam::123456789012:role/tfc-role |
アカウントB用
Variable名 |
値 |
TFC_AWS_PROVIDER_AUTH_accountB |
true |
TFC_AWS_RUN_ROLE_ARN_accountB |
作成したアカウントBのIAMロールARN 例:arn:aws:iam::987654321098:role/tfc-role |
ポイントは、変数名にサフィックスとして付与している_accountA
とか_accountB
のところです。変数の値はシングルアカウントの時と全く同じです。
サフィックス文字列自体は何でも良いのですが、後述のTerraformコードで、AWSプロバイダのエイリアスとして指定します。
providers.tf
に以下のように記載します。
variable "tfc_aws_dynamic_credentials" {
description = "Object containing AWS dynamic credentials configuration"
type = object({
default = object({
shared_config_file = string
})
aliases = map(object({
shared_config_file = string
}))
})
}
provider "aws" {
alias = "accountA"
region = "ap-northeast-1"
shared_config_files = [
var.tfc_aws_dynamic_credentials.aliases["accountA"].shared_config_file,
]
}
provider "aws" {
alias = "accountB"
region = "ap-northeast-1"
shared_config_files = [
var.tfc_aws_dynamic_credentials.aliases["accountB"].shared_config_file,
]
}
コード解説
2〜12行目のvariable "tfc_aws_dynamic_credentials" {...}
ここは決まり文句ですので、公式ドキュメントの内容を何も考えずにコピペします。考えたら負け!
15〜21行目
アカウントAに対する接続の設定になります。Variablesのサフィックスに指定した文字列の先頭アンダースコアを除いたものaccountA
を19行目で指定します。
alias
はコード上で呼び出す際の文字列なので何でも良いのですが、揃えた方がわかりやすいのでaccountA
としています。
24〜30行目
アカウントBに(略
ここまで来たら、あとはリソース作成時に対象AWSアカウント(プロバイダ)を指定するだけです!
resource "aws_instance" "web" {
provider = aws.accountA
...
}
おまけ
terraform.tf
には必ずcloud
ブロックを記載するようにしましょう。
こうすることで、プッシュする前にローカルでterraform plan
する際にも、terraform login
しておくことで設定したDynamic Credential設定を使ってくれていい感じです。
例
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "= 5.66.0"
}
}
required_version = "= 1.9.5"
cloud {
organization = "hoge"
hostname = "app.terraform.io"
workspaces {
name = "fuga"
}
}
}