ここ最近はずっと AWS まわりの構成を Terraform で書いてます. クセはありますがつぶしたりつくったりすぐできるのが容易でいいと思います.
HCL っていう言語らしいですが Qiita ではハイライトできないですね.
で,若干ひっかかったところをメモ:
AWS のポリシーを書くときに JSON を heredoc で書くことがあると思います:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowSpecificIpAddresses", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": [ "es:*" ], "Condition": { "IpAddress": { "aws:SourceIp": [ "9.8.7.6", "10.11.12.13", "100.101.102.103", "11.22.33.44" ] } }, "Resource": "arn:aws:es:ap-northeast-1:000000000000:domain/my-aws-elasticsearch/*" } ] }
このなかで特定の IP のリストに対して、たとえば
locals { allowed_ips = ["9.8.7.6", "10.11.12.13", "100.101.102.103", "11.22.33.44"] }
のように Allow 対象の IP をリストで持っている + リストは variable
とかで渡ってくるという場合、この list
を埋め込む必要があります。
Interpolation?
これに対し普通に Interpolation とかを使うとエラーになりますね:
resource "aws_elasticsearch_domain_policy" "elasticsearch_policy" { domain_name = "${aws_elasticsearch_domain.elasticsearch.domain_name}" access_policies = <<POLICY { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowSpecificIpAddresses", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": [ "es:*" ], "Condition": { "IpAddress": { "aws:SourceIp": "${local.allowed_ips}" } }, "Resource": "${aws_elasticsearch_domain.elasticsearch.arn}/*" } ] } POLICY }
Error: Invalid template interpolation value local.ngw_public_ips is list of string with 2 elements
どうするか
この場合、リソース + heredoc で書くのをやめて、データソースで定義する方法があります
→ aws_iam_role_policy
リソースに対して
aws_iam_policy_document
データソースを使えるように:
https://www.terraform.io/docs/providers/aws/guides/iam-policy-documents.html
ただ、aws_elasticsearch_domain_policy
のようにデータソースで記述できないケースがあります:
https://www.terraform.io/docs/providers/aws/r/elasticsearch_domain_policy.html
jsonencode
を使う
その場合 join
を駆使して……とか考えますが、
そうしなくとも jsonencode
を使うのが楽です:
resource "aws_elasticsearch_domain_policy" "elasticsearch_policy" { domain_name = "${aws_elasticsearch_domain.elasticsearch.domain_name}" access_policies = <<POLICY { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowSpecificIpAddresses", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": [ "es:*" ], "Condition": { "IpAddress": { "aws:SourceIp": ${jsonencode(local.allowed_ips)} } }, "Resource": "${aws_elasticsearch_domain.elasticsearch.arn}/*" } ] } POLICY }
こうすることで ${jsonencode(local.allowed_ips)}
は
["9.8.7.6", "10.11.12.13", ...]
と JSON の Array
に展開されるので、
そのまま書くことができます。
余談
もし各要素に対して map
的な操作が必要であれば、
バージョン 0.12
から List Comprehension が使えるようになったので、
簡単に各要素を変更することができるようになりました:
https://github.com/hashicorp/terraform/issues/8439
Qiita にも同じ内容で投稿してます が重複コンテンツ扱いになったりするだろうか……
👉 よろしければ Twitter でフォロー をお願いいたします.