Use Terraform to create a VPC firewall to protect traffic between two VPCs connected by using an Express Connect circuit

Updated at:

Provision a VPC firewall that inspects traffic between two VPCs connected by an Express Connect circuit. The Terraform configuration in this topic creates all required resources in a single terraform apply run: two VPCs with vSwitches, a peering connection, route entries, and the firewall itself.

Run the sample code in this topic directly in your browser. Visit Terraform Explorer.

Prerequisites

Before you begin, ensure that you have:

  • A RAM user with an AccessKey pair. Avoid using your Alibaba Cloud root account for day-to-day operations. See Create a RAM user and Create an AccessKey.

  • The following permissions granted to your RAM user. See Grant permissions to RAM users. <details> <summary>Required RAM policy</summary>

    {
        "Version": "1",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "yundun-cloudfirewall:*",
                    "yundun-ndr:*",
                    "vpc:CreateVpc",
                    "vpc:DeleteVpc",
                    "vpc:DescribeVpcs",
                    "vpc:CreateVSwitch",
                    "vpc:DeleteVSwitch",
                    "vpc:DescribeVSwitches",
                    "vpc:CreateRouteEntry",
                    "vpc:DeleteRouteEntry",
                    "vpc:DescribeRouteEntries",
                    "vpc:CreateVpcPeerConnection",
                    "vpc:DeleteVpcPeerConnection",
                    "vpc:DescribeVpcPeerConnections",
                    "cloudfirewall:CreateVpcFirewall",
                    "cloudfirewall:DeleteVpcFirewall",
                    "cloudfirewall:DescribeVpcFirewalls"
                ],
                "Resource": "*"
            }
        ]
    }

    </details>

  • Terraform 0.12.28 or later. Run terraform --version to check. Choose one of the following environments:

Resources used

alicloud_cloud_firewall_vpc_firewall: VPCboundary firewall。

Create a VPC firewall

Step 1: Write the configuration

Create a working directory and a main.tf file inside it. The following configuration provisions all required resources in sequence: two VPCs with vSwitches, a peering connection, route entries, and the VPC firewall.

Provider and VPCs

The configuration targets the cn-heyuan region. It creates two VPCs with non-overlapping CIDR blocks and two vSwitches in each VPC across two availability zones.

variable "region" {
  default = "cn-heyuan"
}
provider "alicloud" {
  region = var.region
}
# Retrieve the current Alibaba Cloud account ID.
data "alicloud_account" "current" {
}
# VPC 1 (initiator)
resource "alicloud_vpc" "vpc" {
  vpc_name   = "dd-tf-vpc-01"
  cidr_block = "192.168.0.0/16"
}
# VPC 2 (acceptor)
resource "alicloud_vpc" "vpc1" {
  vpc_name   = "dd-tf-vpc-02"
  cidr_block = "172.16.0.0/12"
}
# vSwitches for VPC 1
resource "alicloud_vswitch" "vsw" {
  vpc_id       = alicloud_vpc.vpc.id
  cidr_block   = "192.168.10.0/24"
  zone_id      = "cn-heyuan-a"
  vswitch_name = "dd-tf-vpc-01-example-1"
}
resource "alicloud_vswitch" "vsw1" {
  vpc_id       = alicloud_vpc.vpc.id
  cidr_block   = "192.168.20.0/24"
  zone_id      = "cn-heyuan-b"
  vswitch_name = "dd-tf-vpc-01-example-2"
}
# vSwitches for VPC 2
resource "alicloud_vswitch" "vsw2" {
  vpc_id       = alicloud_vpc.vpc1.id
  cidr_block   = "172.16.10.0/24"
  zone_id      = "cn-heyuan-a"
  vswitch_name = "dd-tf-vpc-02-example-11"
}
resource "alicloud_vswitch" "vsw3" {
  vpc_id       = alicloud_vpc.vpc1.id
  cidr_block   = "172.16.20.0/24"
  zone_id      = "cn-heyuan-b"
  vswitch_name = "dd-tf-vpc-02-example-22"
}

VPC peering connection

The peering connection links VPC 1 (initiator) to VPC 2 (acceptor). Both VPCs are in the same region, so accepting_region_id matches the provider region.

resource "alicloud_vpc_peer_connection" "default" {
  peer_connection_name = "terraform-example-vpc-peer-connection"
  vpc_id               = alicloud_vpc.vpc.id
  accepting_ali_uid    = data.alicloud_account.current.id
  accepting_region_id  = "cn-heyuan"
  accepting_vpc_id     = alicloud_vpc.vpc1.id
  description          = "terraform-example"
  force_delete         = true
}
resource "alicloud_vpc_peer_connection_accepter" "default" {
  instance_id  = alicloud_vpc_peer_connection.default.id
  force_delete = true
}

Route entries

Each VPC needs a route entry that directs traffic destined for the peer's CIDR block through the peering connection.

# Route from VPC 1 toward VPC 2
resource "alicloud_route_entry" "foo" {
  route_table_id        = alicloud_vpc.vpc.route_table_id
  destination_cidrblock = "1.2.3.4/32"
  nexthop_type          = "VpcPeer"
  nexthop_id            = alicloud_vpc_peer_connection.default.id
}
# Route from VPC 2 toward VPC 1
resource "alicloud_route_entry" "foo1" {
  route_table_id        = alicloud_vpc.vpc1.route_table_id
  destination_cidrblock = "4.3.X.X/32"
  nexthop_type          = "VpcPeer"
  nexthop_id            = alicloud_vpc_peer_connection.default.id
}

Wait resources

The VPC firewall API requires the peering connection and route entries to be fully propagated before the firewall can be created. The time_sleep resource introduces a 12-minute wait (720 seconds) for propagation. Adjust create_duration based on your network conditions.

resource "time_sleep" "wait_before_firewall" {
  depends_on = [
    alicloud_route_entry.foo,
    alicloud_route_entry.foo1
  ]
  create_duration = "720s"
}
resource "null_resource" "wait_for_firewall" {
  provisioner "local-exec" {
    command = "echo waiting for firewall to be ready"
  }
  depends_on = [time_sleep.wait_before_firewall]
}

VPC firewall

The alicloud_cloud_firewall_vpc_firewall resource creates the firewall. It references both VPCs, their route tables, and the peering connection as the next hop. Setting status = "open" enables the firewall immediately after creation.

resource "alicloud_cloud_firewall_vpc_firewall" "default" {
  depends_on = [null_resource.wait_for_firewall]
  timeouts {
    create = "30m"
  }
  vpc_firewall_name = "tf-test"
  member_uid        = data.alicloud_account.current.id
  local_vpc {
    vpc_id    = alicloud_vpc.vpc.id
    region_no = "cn-heyuan"
    local_vpc_cidr_table_list {
      local_route_table_id = alicloud_vpc.vpc.route_table_id
      local_route_entry_list {
        local_next_hop_instance_id = alicloud_vpc_peer_connection.default.id
        local_destination_cidr     = alicloud_route_entry.foo.destination_cidrblock
      }
    }
  }
  peer_vpc {
    vpc_id    = alicloud_vpc.vpc1.id
    region_no = "cn-heyuan"
    peer_vpc_cidr_table_list {
      peer_route_table_id = alicloud_vpc.vpc1.route_table_id
      peer_route_entry_list {
        peer_destination_cidr      = alicloud_route_entry.foo1.destination_cidrblock
        peer_next_hop_instance_id  = alicloud_vpc_peer_connection.default.id
      }
    }
  }
  # open: enable the firewall immediately after creation
  # close: create the firewall in a disabled state
  status = "open"
}

Outputs

output "vpc_id" {
  value = alicloud_vpc.vpc.id
}
output "vpc1_id" {
  value = alicloud_vpc.vpc1.id
}
output "route_table_id_vpc" {
  value = alicloud_vpc.vpc.route_table_id
}
output "route_table_id_vpc1" {
  value = alicloud_vpc.vpc1.route_table_id
}
output "foo_nexthop_id" {
  value = alicloud_vpc_peer_connection.default.id
}
output "foo1_nexthop_id" {
  value = alicloud_vpc_peer_connection.default.id
}
output "cidrblock" {
  value = alicloud_route_entry.foo.destination_cidrblock
}
output "cidrblock1" {
  value = alicloud_route_entry.foo1.destination_cidrblock
}

Step 2: Initialize Terraform

terraform init

Terraform downloads the aliyun/alicloud provider and initializes the working directory. A successful run ends with:

Terraform has been successfully initialized!
For Terraform 0.13 and later, the provider source has moved to aliyun/alicloud. Update required_providers in your configuration if you see a registry warning.

Step 3: Preview the execution plan

terraform plan

Review the list of resources Terraform will create before applying changes.

Step 4: Apply the configuration

terraform apply

When prompted, enter yes and press Enter. The process takes approximately 25 minutes because of the 12-minute propagation wait and the firewall creation. A successful run ends with:

Apply complete! Resources: 13 added, 0 changed, 0 destroyed.

Verify the result

Using the CLI

List all resources in the Terraform state and inspect the firewall details:

terraform state list
terraform show

The terraform show output includes the firewall ID (prefixed with vfw-) and its current status. Verify that status is open and that vpc_firewall_name is tf-test.

Using the console

  1. Log on to the Cloud Firewall console.

  2. Go to Cloud Firewall consoleFirewall Settings and click the VPC Firewall tab.

  3. Search for the firewall by its ID to view its configuration and status.

image

Clean up resources

To delete all resources created by this configuration:

terraform destroy

For more information, see Common commands.

Complete sample code

Run the sample code directly in your browser at Terraform Explorer.
variable "region" {
  default = "cn-heyuan"
}
provider "alicloud" {
  region = var.region
}
data "alicloud_account" "current" {
}
resource "alicloud_vpc" "vpc" {
  vpc_name   = "dd-tf-vpc-01"
  cidr_block = "192.168.0.0/16"
}
resource "alicloud_vpc" "vpc1" {
  vpc_name   = "dd-tf-vpc-02"
  cidr_block = "172.16.0.0/12"
}
resource "alicloud_vswitch" "vsw" {
  vpc_id       = alicloud_vpc.vpc.id
  cidr_block   = "192.168.10.0/24"
  zone_id      = "cn-heyuan-a"
  vswitch_name = "dd-tf-vpc-01-example-1"
}
resource "alicloud_vswitch" "vsw1" {
  vpc_id       = alicloud_vpc.vpc.id
  cidr_block   = "192.168.20.0/24"
  zone_id      = "cn-heyuan-b"
  vswitch_name = "dd-tf-vpc-01-example-2"
}
resource "alicloud_vswitch" "vsw2" {
  vpc_id       = alicloud_vpc.vpc1.id
  cidr_block   = "172.16.10.0/24"
  zone_id      = "cn-heyuan-a"
  vswitch_name = "dd-tf-vpc-02-example-11"
}
resource "alicloud_vswitch" "vsw3" {
  vpc_id       = alicloud_vpc.vpc1.id
  cidr_block   = "172.16.20.0/24"
  zone_id      = "cn-heyuan-b"
  vswitch_name = "dd-tf-vpc-02-example-22"
}
resource "alicloud_vpc_peer_connection" "default" {
  peer_connection_name = "terraform-example-vpc-peer-connection"
  vpc_id               = alicloud_vpc.vpc.id
  accepting_ali_uid    = data.alicloud_account.current.id
  accepting_region_id  = "cn-heyuan"
  accepting_vpc_id     = alicloud_vpc.vpc1.id
  description          = "terraform-example"
  force_delete         = true
}
resource "alicloud_vpc_peer_connection_accepter" "default" {
  instance_id  = alicloud_vpc_peer_connection.default.id
  force_delete = true
}
resource "alicloud_route_entry" "foo" {
  route_table_id        = alicloud_vpc.vpc.route_table_id
  destination_cidrblock = "1.2.3.4/32"
  nexthop_type          = "VpcPeer"
  nexthop_id            = alicloud_vpc_peer_connection.default.id
}
resource "alicloud_route_entry" "foo1" {
  route_table_id        = alicloud_vpc.vpc1.route_table_id
  destination_cidrblock = "4.3.X.X/32"
  nexthop_type          = "VpcPeer"
  nexthop_id            = alicloud_vpc_peer_connection.default.id
}
resource "time_sleep" "wait_before_firewall" {
  depends_on = [
    alicloud_route_entry.foo,
    alicloud_route_entry.foo1
  ]
  create_duration = "720s"
}
resource "null_resource" "wait_for_firewall" {
  provisioner "local-exec" {
    command = "echo waiting for firewall to be ready"
  }
  depends_on = [time_sleep.wait_before_firewall]
}
resource "alicloud_cloud_firewall_vpc_firewall" "default" {
  depends_on = [null_resource.wait_for_firewall]
  timeouts {
    create = "30m"
  }
  vpc_firewall_name = "tf-test"
  member_uid        = data.alicloud_account.current.id
  local_vpc {
    vpc_id    = alicloud_vpc.vpc.id
    region_no = "cn-heyuan"
    local_vpc_cidr_table_list {
      local_route_table_id = alicloud_vpc.vpc.route_table_id
      local_route_entry_list {
        local_next_hop_instance_id = alicloud_vpc_peer_connection.default.id
        local_destination_cidr     = alicloud_route_entry.foo.destination_cidrblock
      }
    }
  }
  peer_vpc {
    vpc_id    = alicloud_vpc.vpc1.id
    region_no = "cn-heyuan"
    peer_vpc_cidr_table_list {
      peer_route_table_id = alicloud_vpc.vpc1.route_table_id
      peer_route_entry_list {
        peer_destination_cidr     = alicloud_route_entry.foo1.destination_cidrblock
        peer_next_hop_instance_id = alicloud_vpc_peer_connection.default.id
      }
    }
  }
  status = "open"
}
output "vpc_id" {
  value = alicloud_vpc.vpc.id
}
output "vpc1_id" {
  value = alicloud_vpc.vpc1.id
}
output "route_table_id_vpc" {
  value = alicloud_vpc.vpc.route_table_id
}
output "route_table_id_vpc1" {
  value = alicloud_vpc.vpc1.route_table_id
}
output "foo_nexthop_id" {
  value = alicloud_vpc_peer_connection.default.id
}
output "foo1_nexthop_id" {
  value = alicloud_vpc_peer_connection.default.id
}
output "cidrblock" {
  value = alicloud_route_entry.foo.destination_cidrblock
}
output "cidrblock1" {
  value = alicloud_route_entry.foo1.destination_cidrblock
}