Terraformのリファクタリング楽しいですね。ついついいろんなハードコードを変数化するのに熱中してしまいます。
AWSをTerraformで構築・運用するときAWSのアカウントIDが必要になることがあります。
特にVPC Peering、Private Link, SNS, S3のBucket Policyなど、クロスアカウントで利用できるリソースなどは別アカウントのIDが欲しくなる事があります。
一つならまだしも2つ以上アカウントIDと連携したりすると混乱するので、ここにハードコードしたIDではなくわかりやすい変数名、しかもリモートステートで別アカウントのIDが参照できれば良いなと思いました。
自アカウントであれば、aws_caller_identityを利用すれば簡単に取得することができます。
1
| data "aws_caller_identity" "self" { }
|
どこかに上記のような記述をすると、下記のような形でアカウントIDを参照できます。
1
| "${data.aws_caller_identity.self.account_id}"
|
これにリモートステートの仕組みをプラスすることで、別アカウントのIDを変数化できました。
参照される側のアカウントをA, 参照する側のアカウントをBとしています。
参照される側のアカウントの設定
まずは参照されるアカウントAの設定です。
別アカウントBに変数を公開するにはoutputとして登録する必要があります。
今回は変数名をaccount_idとして、AWSのアカウントIDを公開しています。
1
2
3
4
5
| data "aws_caller_identity" "self" {}
output "account_id" {
value = "${data.aws_caller_identity.self.account_id}"
}
|
また、S3のバケットポリシーを編集して、TerraformのStateをアカウントBが閲覧できるように設定をする必要があります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ExampleStatement1",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::[アカウントBのID]:root",
]
},
"Action": [
"s3:GetBucketLocation",
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::[アカウントAのStateが入っているBucket]",
"arn:aws:s3:::[アカウントAのStateが入っているBucket]"/*"
]
}
]
}
|
参照される側のアカウントの設定
参照する側のアカウントBでは参照するアカウントAのStateを参照する設定を追加します。
1
2
3
4
5
6
7
8
9
| data "terraform_remote_state" "account_a" {
backend = "s3"
config {
bucket = "[アカウントAのStateが入っているBucket]"
key = "state"
region = "ap-northeast-1"
}
}
|
例えばアカウントAとBのVPC Peeringの設定とかで利用できます。
1
2
3
4
5
6
|
resource "aws_vpc_peering_connection" "acount_a_b" {
peer_owner_id = "${data.terraform_remote_state.account_a.account_id}"
peer_vpc_id = "[アカウントAのVPC ID]"
vpc_id = "[アカウントBのVPC ID]"
}
|
アカウントAのVPC IDもリモートステートで取得する手もありますが、今回は割愛しました。
まとめ
Terraformを書いていていろんなアカウントと連携する設定を書くときに、アカウントID部分が数字の羅列だと混乱するので変数化してみました。
クロスアカウントの機能は充実していますし機能拡張もされ続けています。
何かと使い所はあるのではないでしょうか。