🛡️

[Terraform] aws_networkfirewall_firewall リソースから VPC エンドポイント ID を取り出す

2023/03/16に公開

はじめに

Terraform を使って AWS Network Firewall のファイアウォールを作るとき,生成された VPC エンドポイントの ID をサブネットのルートテーブルのルートに追加するのは自然な流れですが,VPC エンドポイント ID を取り出すのが大変だったので,やり方を記録しておきます。

例えば以下のように aws_networkfirewall_firewall リソースを定義したとします。
(特に説明のない変数やリソースは,なんとなくの理解で構いません。)

resource "aws_networkfirewall_firewall" "firewall" {
  name                = "example"
  firewall_policy_arn = aws_networkfirewall_firewall_policy.example.arn
  vpc_id              = module.vpc.vpc_id

  dynamic "subnet_mapping" {
    for_each = module.vpc.private_subnets
    content {
      subnet_id = subnet_mapping.value
    }
  }
}

TL;DR

VPC エンドポイント ID は以下で取り出せます。

[for ss in tolist(aws_networkfirewall_firewall.firewall.firewall_status[0].sync_states) : ss.attachment[0].endpoint_id if ss.availability_zone == "VPC エンドポイントが存在する AZ"][0]

方法

ファイアウォールのリソースの firewall_status 属性の構造は以下のようになっています。

{
  firewall_status = tolist([
    {
      sync_states = toset([
        {
          attachment = tolist([
	    {
              endpoint_id = "vpce-???"  # VPC エンドポイント ID
	      subnet_id = "subnet-???"  # VPC エンドポイントが存在する VPC サブネット ID
            },
	  ])
          availability_zone = "ap-northeast-1a"  # AZ 名
        },
	# {VPC エンドポイントの個数だけ同じ形式が続く…},
      ])
    },
  ])
}

かなり深い階層に存在します。生成された VPC エンドポイントの情報は firewall_status[0].sync_states の set の中に一つずつ入っています。

object 型ならわかりやすいキーを使って絞り込めますが,今回は残念ながら set 型なので,中身を見て絞り込まないといけません。

絞り込むには VPC サブネット ID または AZ が使えます。for 文で sync_states のループを回し,所望の VPC サブネット ID または AZ と一致するものを絞り込むようにすれば,目的の VPC エンドポイント ID が得られます。

結論

AZ で指定する場合をルートテーブルで使用した例を以下に示します。

resource "aws_route_table" "to_public" {
  for_each = toset(local.azs)

  vpc_id = module.vpc.vpc_id

  route {
    cidr_block      = "0.0.0.0/0"
    vpc_endpoint_id = [for ss in tolist(aws_networkfirewall_firewall.firewall.firewall_status[0].sync_states) : ss.attachment[0].endpoint_id if ss.availability_zone == each.value][0]
  }
}

VPC サブネット ID で絞り込むなら if 文を以下に置き換えます。

if ss.attachment[0].subnet_id == "subnet-???"

参考

同じことを思っている人がたくさんいました。

https://github.com/hashicorp/terraform-provider-aws/issues/16759

Discussion