使用 Terraform AWS Provider 搭建跨账户 Network Firewall 与 Transit Gateway 附件示例

📅 发布时间:2026/9/17 6:47:55
使用 Terraform AWS Provider 搭建跨账户 Network Firewall 与 Transit Gateway 附件示例
使用 Terraform AWS Provider 搭建跨账户 Network Firewall 与 Transit Gateway 附件示例【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws本指南围绕 terraform-provider-aws 仓库中的examples/network-firewall-cross-account-transit-gateway示例展开完整演示如何在账户 A 中创建 EC2 Transit Gateway 并通过 AWS Resource Access ManagerRAM共享给账户 B再让账户 B 将 Network Firewall 防火墙以 Transit Gateway 附件的形式接入该共享网关最后由账户 A 接受附件。读完本文你将掌握双 Provider 多账户编排、RAM 资源共享、跨账户 Network Firewall 附件创建与接受aws_networkfirewall_firewall_transit_gateway_attachment_accepter的完整实战方案并理解 Provider 底层对附件状态的轮询等待机制。示例概览一个跨账户、跨资源类型的完整链路该示例的核心目标是让防火墙和 VPC 网关分属不同 AWS 账户但协同工作。整体拓扑包含两类角色第一个账户first拥有 EC2 Transit Gateway创建 RAM 资源共享并最终接受 Network Firewall 提交的 Transit Gateway 附件请求。第二个账户second拥有 Network Firewall 防火墙及其策略通过共享的 Transit Gateway ID 发起附件并将防火墙流量接入该网关。整条资源依赖链来自 main.tf如下aws_ec2_transit_gateway账户 first——创建共享中转网关aws_ram_resource_shareaws_ram_resource_associationaws_ram_principal_association账户 first——创建资源共享把 TGW 关联进共享并把第二个账户通过aws_caller_identity动态取得其账号 ID设为共享主体aws_networkfirewall_firewall_policy账户 second——定义无状态默认动作aws_networkfirewall_firewall账户 second——设置transit_gateway_id并声明depends_on确保 RAM 关联完成后再发起附件aws_networkfirewall_firewall_transit_gateway_attachment_accepter账户 first——读取防火墙状态中的附件 ID 并接受完成跨账户接入。前置条件同一组织与 RAM 服务原文档 README.md 明确列出两项硬性前提缺一不可两个 AWS 账户必须位于同一个 AWS Organizations 组织内。跨账户共享 Transit Gateway 依赖组织内的资源共享能力账户之间必须建立组织信任关系。必须在组织中启用 AWS Resource Access ManagerRAM。Transit Gateway 的资源共享、主体验证都由 RAM 承载未启用 RAM 时aws_ram_principal_association将无法完成授权。此外运行本示例还需要两个账户各自的访问密钥aws_first_access_key/aws_second_access_key及对应 Secret Key并选择一个两个账户均可访问的区域示例默认us-east-1。多账户配置双 Provider 与变量定义变量声明variables.tf 声明了 5 个无默认值变量全部由调用方在运行时注入variable aws_first_access_key {} variable aws_first_secret_key {} variable aws_second_access_key {} variable aws_second_secret_key {} variable aws_region {}Provider 配置main.tf 顶部通过alias声明了两个独立的 AWS Provider 实例同一份配置即可同时操作两个账户互不干扰terraform { required_version 0.12 } # First account owns the transit gateway and accepts the Network Firewall attachment. provider aws { alias first region var.aws_region access_key var.aws_first_access_key secret_key var.aws_first_secret_key } # Second account owns the Network Firewall and creates the VPC attachment. provider aws { alias second region var.aws_region access_key var.aws_second_access_key secret_key var.aws_second_secret_key }这里采用了最直观的凭证注入方式Access Key 直填。生产环境中更推荐改用profile或assume_role等替身凭证方式避免密钥直接出现在命令行或变量文件中示例的terraform.template.tfvars提供了一套可替换的占位凭证见下文运行示例一节。逐步拆解 main.tf五个资源如何协同1. 数据源准备data aws_availability_zones available { provider aws.first filter { name opt-in-status values [opt-in-not-required] } } data aws_caller_identity second { provider aws.second }aws_availability_zones过滤出默认开启的可用区opt-in-not-required用于给防火墙选取第一个可用区映射避免选择需要手动启用的本地或新开放区域aws_caller_identity以账户 second 的身份调用 STS动态取得其 12 位账号 ID供 RAM 主体验证使用避免硬编码账号号。2. 账户 first创建并共享 Transit Gatewayresource aws_ec2_transit_gateway example { provider aws.first tags { Name terraform-example } } resource aws_ram_resource_share example { provider aws.first name terraform-example tags { Name terraform-example } } # Share the transit gateway... resource aws_ram_resource_association example { provider aws.first resource_arn aws_ec2_transit_gateway.example.arn resource_share_arn aws_ram_resource_share.example.id } # ...with the second account. resource aws_ram_principal_association example { provider aws.first principal data.aws_caller_identity.second.account_id resource_share_arn aws_ram_resource_share.example.id }三段式共享模型aws_ram_resource_share先创建空的资源共享容器aws_ram_resource_association把 TGW 的 ARN 挂进共享aws_ram_principal_association把账户 second 的账号 ID 加入共享主体列表TGW 即对账户 second 可见、可用。3. 账户 second创建防火墙策略与防火墙resource aws_networkfirewall_firewall_policy example { provider aws.second name terraform-example firewall_policy { stateless_fragment_default_actions [aws:drop] stateless_default_actions [aws:pass] } } # Create Network Firewall in the second account attached to the shared transit gateway resource aws_networkfirewall_firewall example { provider aws.second depends_on [ aws_ram_resource_association.example, aws_ram_principal_association.example, ] name terraform-example firewall_policy_arn aws_networkfirewall_firewall_policy.example.arn transit_gateway_id aws_ec2_transit_gateway.example.id availability_zone_mapping { availability_zone_id data.aws_availability_zones.available.zone_ids[0] } }关键点说明策略定义了两个无状态默认动作分片数据包默认aws:drop完整数据包默认aws:pass形成分片丢弃、主流量放行的基线实际规则可在stateless_rule_group_reference/stateful_rule_group_reference中继续补充防火墙通过transit_gateway_id引用账户 first 创建的 TGW这是跨账户能力的关键参数。从 firewall.go 的 schema 可见transit_gateway_id与vpc_id互为排斥ExactlyOneOf且二者都是ForceNew——即防火墙要么接入 TGW、要么接入 VPC切换模式必须重建资源depends_on强制保证 RAM 关联与主体验证先完成否则防火墙创建时可能因 TGW 尚未共享给本账户而失败availability_zone_mapping至少需要一个可用区映射此处取数据源返回的第一个可用区 ID。4. 账户 first接受跨账户附件# ...and accept it in the first account. resource aws_networkfirewall_firewall_transit_gateway_attachment_accepter example { provider aws.first transit_gateway_attachment_id aws_networkfirewall_firewall.example.firewall_status[0].transit_gateway_attachment_sync_states[0].attachment_id }账户 second 发起附件后账户 first 侧必须显式接受。附件 ID 并非直接暴露在防火墙主属性上而是从计算属性firewall_status[0].transit_gateway_attachment_sync_states[0].attachment_id中提取——这正是 firewall.go 中firewall_status块里transit_gateway_attachment_sync_states含attachment_id计算字段所定义的输出结构属于 AWS 返回给防火墙的同步状态信息。运行示例原文档给出了两种运行方式。方式一复制模板变量文件并修改cp terraform.template.tfvars terraform.tfvarsterraform.template.tfvars 内容如下占位凭证需替换为真实密钥# First account aws_first_access_key AAAAAAAAAAAAAAAAAAA aws_first_secret_key SuperSecretKeyForAccount1 # Second account aws_second_access_key BBBBBBBBBBBBBBBBBBB aws_second_secret_key SuperSecretKeyForAccount2 aws_region us-east-1方式二通过 CLI 直接传参terraform apply \ -varaws_first_access_keyAAAAAAAAAAAAAAAAAAA \ -varaws_first_secret_keySuperSecretKeyForAccount1 \ -varaws_second_access_keyBBBBBBBBBBBBBBBBBBB \ -varaws_second_secret_keySuperSecretKeyForAccount2 \ -varaws_regionus-east-1两种方式等价推荐前者以便把敏感信息留在本地文件中注意将terraform.tfvars加入版本控制忽略清单。源码级原理accepter 资源的实现细节仓库中 firewall_transit_gateway_attachment_accepter.go 是aws_networkfirewall_firewall_transit_gateway_attachment_accepter的框架式Terraform Plugin Framework实现值得关注的实现事实Schema 极简仅包含一个必填属性transit_gateway_attachment_id且带RequiresReplace计划修饰符即附件 ID 一旦变化就销毁重建同时暴露timeoutsCreate/Delete 默认各 60 分钟。Create 即调用接受 APICreate直接调用 Network Firewall 客户端的AcceptNetworkFirewallTransitGatewayAttachment传入附件 ID随后转入 EC2 客户端的WaitTransitGatewayAttachmentAccepted轮询等待直到附件状态变为accepted才把状态写入 State。也就是说terraform apply会阻塞直到跨账户接受真正生效。Read 做存在性校验通过 EC2 的FindTransitGatewayAttachmentByID查询附件若状态为deleted或已不存在则按资源已消失处理从 State 中移除。Delete 走删除 API调用DeleteNetworkFirewallTransitGatewayAttachment并对ResourceNotFoundException做幂等容错已不存在则直接返回成功随后同样等待删除完成。支持导入ImportState使用 Passthrough 方式直接以transit_gateway_attachment_id作为导入 ID。配套的 firewall_transit_gateway_attachment_accepter_test.go 提供了该资源的接受测试用例可作为编写跨账户场景测试的参考基线。运维与排障要点执行顺序依赖账户 second 的防火墙强依赖 RAM 共享完成切勿移除depends_on若遇到TGW 不存在或不可访问类错误优先检查 RAM 共享的关联与主体验证是否已生效。附件 ID 提取firewall_status[0].transit_gateway_attachment_sync_states[0].attachment_id是计算属性取决于 AWS 返回的同步状态读取前请确认防火墙确实处于transit_gateway_id模式而非vpc_id模式。60 分钟超时Create/Delete 默认超时均为 60 分钟大规模跨账户拓扑或跨区域同步较慢时可通过timeouts块调整。凭证安全示例为演示目的使用 Access Key 直传建议生产环境改用 IAM Role 与assume_role/profile组合并结合data aws_caller_identity动态解析账号保持配置可移植。至此你已拥有一个可直接运行的跨账户 Network Firewall Transit Gateway 参考实现从 TGW 创建、RAM 共享、防火墙创建到附件接受的全链路既可在 examples/network-firewall-cross-account-transit-gateway 目录中查看完整源码也可对照 Provider 内部实现internal/service/networkfirewall深入理解每个资源背后的 API 调用与状态等待机制。【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考