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
そもそも IP 制限とかではなく IAM ロールを使ったほうがいいってのはあります……