
マルチアカウント間の通信にTransit Gatewayを使う場合、以下の記事にあるようにResouce Access Managerを使ってリソース共有を行う必要があります。
Organizations環境でTerraformを使ってやってみたのでメモ。なお、Organizationsの設定でAWS Resource Access Managerは有効になっている前提です。

目次
構成とコード

READMEに従えばできるはず。TF_VARS_*使えばvariables.tf修正する必要もないですね。
少し補足。
- 実際には使いませんが、パブリックサブネットやInternet Gatewayも作ってます(他に色々試す場合にどうせ必要になるので)
- EC2インスタンスは手動で適当に立てればいいです。
- EC2インスタンスへのログインはSession Manager使えばいいと思います。VPCエンドポイントはTerraformで作成してます。
- ただし、Session Manager使うためのIAMロールは作ってません。Systems Manager Quick Setupで作成されるAmazonSSMRoleForInstancesQuickSetup使えばいいかと思います。もちろん作ってもよし。
- プライベートサブネットが各リージョンごとに複数あるのは、Transit Gatewayにアタッチされているサブネット以外からもアクセスできるということの確認のためです。
解説
Transit Gatewayの作成はモジュール化してます。OwnerとUserをうまく共通化する方法が思いつかなかったので、別モジュールになってます。
Owner側
variable "vpc_id" {}
variable "private_subnet_ids" {}
variable "private_rtb_id" {}
variable "user_account" {}
variable "user_cidr" {}
resource "aws_ec2_transit_gateway" "tgw" {
dns_support = "enable"
vpn_ecmp_support = "disable"
default_route_table_association = "enable"
default_route_table_propagation = "enable"
auto_accept_shared_attachments = "enable"
}
resource "aws_ec2_transit_gateway_vpc_attachment" "tgw-attachment" {
transit_gateway_id = aws_ec2_transit_gateway.tgw.id
vpc_id = var.vpc_id
subnet_ids = var.private_subnet_ids
dns_support = "enable"
}
resource "aws_ram_resource_share" "tgw" {
name = "tgw"
allow_external_principals = true
tags = {
Name = "tgw"
}
}
resource "aws_ram_resource_association" "tgw" {
resource_arn = aws_ec2_transit_gateway.tgw.arn
resource_share_arn = aws_ram_resource_share.tgw.arn
}
resource "aws_ram_principal_association" "tgw" {
principal = var.user_account
resource_share_arn = aws_ram_resource_share.tgw.arn
}
resource "aws_route" "route_tgw" {
route_table_id = var.private_rtb_id
destination_cidr_block = var.user_cidr
transit_gateway_id = aws_ec2_transit_gateway.tgw.id
}
Owner側では、
- Transit Gatewayを作成
- Resouce SharingでUserアカウントに共有
します。アカウント間のリソース共有は共有元・共有先の両方で設定しないといけないので、書き方いまいちピンとこないうちは試行錯誤してましたが、つながってみればほぼマニュアル通りな感じでした。
User側
variable "vpc_id" {}
variable "private_subnet_ids" {}
variable "private_rtb_id" {}
variable "owner_account" {}
variable "owner_cidr" {}
data "aws_ec2_transit_gateway" "tgw" {
filter {
name = "owner-id"
values = [var.owner_account]
}
}
resource "aws_ec2_transit_gateway_vpc_attachment" "example" {
vpc_id = var.vpc_id
subnet_ids = var.private_subnet_ids
transit_gateway_id = data.aws_ec2_transit_gateway.tgw.id
dns_support = "enable"
}
resource "aws_route" "route_tgw" {
route_table_id = var.private_rtb_id
destination_cidr_block = var.owner_cidr
transit_gateway_id = data.aws_ec2_transit_gateway.tgw.id
}
User側では、Ownerが作成したTransit Gatewayを使うだけなので、dataリソースで読んでいます。Organizations環境でAWS Resource Access Managerが有効になっているので、とてもかんたんですね。
OrganizationsでAWS Resource Access Managerが無効になっている場合や、別組織のアカウントとのリソース共有では、ram_resource_share_accepterを使う必要があるようです(が試してないのでわからない)。詳しくはドキュメント見てください。
まとめ
Transit Gatewayとかリソース共有殆ど触ったことなかったので、一通りできてよかったし、モジュールの作り方もやっとわかった。これでいつでも作って壊せる環境ができたのでいろいろ試してみたいと思います。