Welcome to TF Automation

Amazon Web Services (AWS) provides a Site-to-Site VPN service that allows you to securely connect your on-premises network or branch office to your AWS Virtual Private Cloud (VPC). This service extends your on-premises network to the cloud over an encrypted VPN connection.

With AWS Site-to-Site VPN, you can connect your on-premises network or branch office to one or more VPCs located in different AWS Regions or in different accounts. This enables you to establish secure connectivity between your on-premises network and your AWS resources as if they were part of the same network.

The following are the components of AWS Site-to-Site VPN:

  1. Virtual Private Gateway (VPG): A VPG is the AWS side of the VPN connection. It is a logical representation of a VPN gateway that you configure in your VPC. You create a VPG and attach it to your VPC. It provides two VPN endpoints for your on-premises network to connect to.
  2. Customer Gateway (CGW): A CGW is the physical device or software application on your on-premises network that acts as the VPN endpoint. You create a CGW and configure the VPN settings on it.
  3. VPN Connection: A VPN connection is the actual connection between the VPG and the CGW. You create a VPN connection and specify the configuration information for the VPG and CGW.
  4. VPN Tunnel: A VPN tunnel is a secure, encrypted connection between the VPG and the CGW. Each VPN connection can have up to two VPN tunnels.
  5. Routing: Once the VPN connection is established, you need to configure the routing so that traffic can flow between your on-premises network and your VPC. You can use static routes or BGP (Border Gateway Protocol) to configure the routing.
  6. Transit Gateway (Optional): A Transit Gateway is a network transit hub that allows you to connect multiple VPCs and on-premises networks together. You can use a Transit Gateway to simplify your network architecture and reduce the number of VPN connections you need to manage.

please find my simple main.yaml file.

resource "aws_customer_gateway" "customer_gateway" {
bgp_asn = var.customer_gateway_bgp_asn
ip_address = var.customer_gateway_ip_address
type = var.customer_gateway_type
device_name = var.customer_gateway_device_name
certificate_arn = var.customer_gateway_certificate_arn

tags = var.tags
}

resource "aws_vpn_gateway" "virtual_private_gateways" {
vpc_id = var.virtual_private_gateways_vpc_id
amazon_side_asn = var.virtual_private_gateways_amazon_side_asn
availability_zone = var.virtual_private_gateways_availability_zone

tags = var.tags
}

resource "aws_vpn_gateway_route_propagation" "route_propagation" {
count = length(var.route_propagation_route_table_ids)
vpn_gateway_id = join("", aws_vpn_gateway.virtual_private_gateways.*.id)
route_table_id = element(var.route_propagation_route_table_ids, count.index)
}

resource "aws_vpn_connection" "vpn_connection" {
customer_gateway_id = join("", aws_customer_gateway.customer_gateway.*.id)
vpn_gateway_id = var.vpn_connection_transit_gateway_id != null ? null : join("", aws_vpn_gateway.virtual_private_gateways.*.id)
type = var.customer_gateway_type
static_routes_only = var.vpn_connection_static_routes_only
local_ipv4_network_cidr = var.vpn_connection_local_ipv4_network_cidr
outside_ip_address_type = var.vpn_connection_outside_ip_address_type
remote_ipv4_network_cidr = var.vpn_connection_remote_ipv4_network_cidr
transport_transit_gateway_attachment_id = var.vpn_connection_transport_transit_gateway_attachment_id

transit_gateway_id = var.vpn_connection_transit_gateway_id != null ? var.vpn_connection_transit_gateway_id : null
enable_acceleration = var.vpn_connection_transit_gateway_id != null ? var.vpn_connection_enable_acceleration : null
local_ipv6_network_cidr = var.vpn_connection_transit_gateway_id != null ? var.vpn_connection_local_ipv6_network_cidr : null
remote_ipv6_network_cidr = var.vpn_connection_transit_gateway_id != null ? var.vpn_connection_remote_ipv6_network_cidr : null
tunnel1_inside_ipv6_cidr = var.vpn_connection_transit_gateway_id != null ? var.vpn_connection_tunnel1_inside_ipv6_cidr : null
tunnel2_inside_ipv6_cidr = var.vpn_connection_transit_gateway_id != null ? var.vpn_connection_tunnel2_inside_ipv6_cidr : null

###vpn_connection_tunnel
tunnel_inside_ip_version = var.vpn_connection_tunnel_inside_ip_version

tunnel1_inside_cidr = var.vpn_connection_tunnel1_inside_cidr
tunnel1_preshared_key = var.vpn_connection_tunnel1_preshared_key
tunnel1_dpd_timeout_action = var.vpn_connection_tunnel1_dpd_timeout_action
tunnel1_dpd_timeout_seconds = var.vpn_connection_tunnel1_dpd_timeout_seconds
tunnel1_ike_versions = var.vpn_connection_tunnel1_ike_versions
tunnel1_phase1_dh_group_numbers = var.vpn_connection_tunnel1_phase1_dh_group_numbers
tunnel1_phase1_encryption_algorithms = var.vpn_connection_tunnel1_phase1_encryption_algorithms
tunnel1_phase1_integrity_algorithms = var.vpn_connection_tunnel1_phase1_integrity_algorithms
tunnel1_phase1_lifetime_seconds = var.vpn_connection_tunnel1_phase1_lifetime_seconds
tunnel1_phase2_dh_group_numbers = var.vpn_connection_tunnel1_phase2_dh_group_numbers
tunnel1_phase2_encryption_algorithms = var.vpn_connection_tunnel1_phase2_encryption_algorithms
tunnel1_phase2_integrity_algorithms = var.vpn_connection_tunnel1_phase2_integrity_algorithms
tunnel1_phase2_lifetime_seconds = var.vpn_connection_tunnel1_phase2_lifetime_seconds
tunnel1_rekey_fuzz_percentage = var.vpn_connection_tunnel1_rekey_fuzz_percentage
tunnel1_rekey_margin_time_seconds = var.vpn_connection_tunnel1_rekey_margin_time_seconds
tunnel1_replay_window_size = var.vpn_connection_tunnel1_replay_window_size
tunnel1_startup_action = var.vpn_connection_tunnel1_startup_action
tunnel1_log_options {
dynamic "cloudwatch_log_options" {
for_each = var.tunnel1_log_options
content {
log_enabled = cloudwatch_log_options.value.log_enabled
log_group_arn = cloudwatch_log_options.value.log_group_arn
log_output_format = cloudwatch_log_options.value.log_output_format
}
}
}

tunnel2_inside_cidr = var.vpn_connection_tunnel2_inside_cidr
tunnel2_preshared_key = var.vpn_connection_tunnel2_preshared_key
tunnel2_dpd_timeout_action = var.vpn_connection_tunnel2_dpd_timeout_action
tunnel2_dpd_timeout_seconds = var.vpn_connection_tunnel2_dpd_timeout_seconds
tunnel2_ike_versions = var.vpn_connection_tunnel2_ike_versions
tunnel2_phase1_dh_group_numbers = var.vpn_connection_tunnel2_phase1_dh_group_numbers
tunnel2_phase1_encryption_algorithms = var.vpn_connection_tunnel2_phase1_encryption_algorithms
tunnel2_phase1_integrity_algorithms = var.vpn_connection_tunnel2_phase1_integrity_algorithms
tunnel2_phase1_lifetime_seconds = var.vpn_connection_tunnel2_phase1_lifetime_seconds
tunnel2_phase2_dh_group_numbers = var.vpn_connection_tunnel2_phase2_dh_group_numbers
tunnel2_phase2_encryption_algorithms = var.vpn_connection_tunnel2_phase2_encryption_algorithms
tunnel2_phase2_integrity_algorithms = var.vpn_connection_tunnel2_phase2_integrity_algorithms
tunnel2_phase2_lifetime_seconds = var.vpn_connection_tunnel2_phase2_lifetime_seconds
tunnel2_rekey_fuzz_percentage = var.vpn_connection_tunnel2_rekey_fuzz_percentage
tunnel2_rekey_margin_time_seconds = var.vpn_connection_tunnel2_rekey_margin_time_seconds
tunnel2_replay_window_size = var.vpn_connection_tunnel2_replay_window_size
tunnel2_startup_action = var.vpn_connection_tunnel2_startup_action
tunnel2_log_options {
dynamic "cloudwatch_log_options" {
for_each = var.tunnel2_log_options
content {
log_enabled = cloudwatch_log_options.value.log_enabled
log_group_arn = cloudwatch_log_options.value.log_group_arn
log_output_format = cloudwatch_log_options.value.log_output_format
}
}
}

tags = var.tags
}

resource "aws_vpn_connection_route" "vpn_connection_route" {
count = var.virtual_private_gateways_availability_zone == null ? 0 : length(var.vpn_connection_route_destination_cidr_block)
destination_cidr_block = element(var.vpn_connection_route_destination_cidr_block, count.index)
vpn_connection_id = aws_vpn_connection.vpn_connection.id
}

This variable.yaml file

variable "customer_gateway_bgp_asn" {
description = "The ASN of your customer gateway device. The Border Gateway Protocol (BGP) Autonomous System Number (ASN) in the range of 1 ā€“ 2,147,483,647 is supported."
type = number
}
variable "customer_gateway_ip_address" {
description = "Specify the internet-routable IP address for your gateway's external interface; the address must be static and may be behind a device performing network address translation (NAT)."
type = string
default = null
}
variable "customer_gateway_type" {
description = "(Required) The type of customer gateway. The only type AWS supports at this time is \"ipsec.1\"."
type = string
}
variable "customer_gateway_device_name" {
description = "(Optional) Enter a name for the customer gateway device."
type = string
default = null
}
variable "customer_gateway_certificate_arn" {
description = "(Optional) The ARN of a private certificate provisioned in AWS Certificate Manager (ACM)."
type = string
default = null
}
variable "tags" {
description = "common tags for vpn resources."
type = map(string)
}

/*virtual_private_gateways*/
variable "virtual_private_gateways_vpc_id" {
description = "(Required) A create a virtual private gateway, you must attach it to your VPC"
type = string
}
variable "virtual_private_gateways_amazon_side_asn" {
description = "(Optional) The Autonomous System Number (ASN) for the Amazon side of the gateway. If you don't specify an ASN, the virtual private gateway is created with the default ASN."
type = number
default = null
}
variable "virtual_private_gateways_availability_zone" {
description = "(Optional) The Availability Zone for the virtual private gateway."
type = string
default = null
}
variable "vpn_connection_transit_gateway_id" {
description = "(Optional) The ID of the EC2 Transit Gateway."
type = string
default = null
}
/*Route propagation*/
variable "route_propagation_route_table_ids" {
description = "(Optional)The IDs of the route tables for which routes from the Virtual Private Gateway will be propagated"
type = list(string)
default = []
}
variable "vpn_connection_static_routes_only" {
description = "(Optional, Default false) Whether the VPN connection uses static routes exclusively. Static routes must be used for devices that don't support BGP."
type = bool
default = false
}
variable "vpn_connection_enable_acceleration" {
description = "(Optional, Default false) Indicate whether to enable acceleration for the VPN connection. Supports only EC2 Transit Gateway."
type = bool
default = false
}
variable "vpn_connection_local_ipv4_network_cidr" {
description = "(Optional, Default 0.0.0.0/0) The IPv4 CIDR on the customer gateway (on-premises) side of the VPN connection."
type = string
default = null
}
variable "vpn_connection_local_ipv6_network_cidr" {
description = "(Optional, Default ::/0) The IPv6 CIDR on the customer gateway (on-premises) side of the VPN connection."
type = string
default = null
}
variable "vpn_connection_outside_ip_address_type" {
description = "(Optional, Default PublicIpv4) Indicates if a Public S2S VPN or Private S2S VPN over AWS Direct Connect. Valid values are PublicIpv4 | PrivateIpv4"
type = string
default = null
validation {
condition = can(regex("^(PublicIpv4|PrivateIpv4)$", var.vpn_connection_outside_ip_address_type))
error_message = "Invalid input, options: \"PublicIpv4\", \"PrivateIpv4\"."
}
}
variable "vpn_connection_remote_ipv4_network_cidr" {
description = "(Optional, Default 0.0.0.0/0) The IPv4 CIDR on the AWS side of the VPN connection."
type = string
default = null
}
variable "vpn_connection_remote_ipv6_network_cidr" {
description = "(Optional, Default ::/0) The IPv6 CIDR on the customer gateway (on-premises) side of the VPN connection."
type = string
default = null
}
variable "vpn_connection_transport_transit_gateway_attachment_id" {
description = "(Required when outside_ip_address_type is set to PrivateIpv4). The attachment ID of the Transit Gateway attachment to Direct Connect Gateway. The ID is obtained through a data source only."
type = string
default = null
}
##vpn_connection_tunnel
variable "vpn_connection_tunnel_inside_ip_version" {
description = "(Optional, Default ipv4) Indicate whether the VPN tunnels process IPv4 or IPv6 traffic. Valid values are ipv4 | ipv6. ipv6 Supports only EC2 Transit Gateway."
type = string
default = null
validation {
condition = can(regex("^(ipv4|ipv6)$", var.vpn_connection_tunnel_inside_ip_version))
error_message = "Invalid input, options: \"ipv4\", \"ipv6\"."
}
}
variable "vpn_connection_tunnel1_inside_cidr" {
description = " (Optional) The CIDR block of the inside IP addresses for the first VPN tunnel. Valid value is a size /30 CIDR block from the 169.254.0.0/16 range."
type = string
default = null
}
variable "vpn_connection_tunnel2_inside_cidr" {
description = "(Optional) The CIDR block of the inside IP addresses for the second VPN tunnel. Valid value is a size /30 CIDR block from the 169.254.0.0/16 range."
type = string
default = null
}
variable "vpn_connection_tunnel1_inside_ipv6_cidr" {
description = "(Optional) The range of inside IPv6 addresses for the first VPN tunnel. Supports only EC2 Transit Gateway. Valid value is a size /126 CIDR block from the local fd00::/8 range."
type = string
default = null
}
variable "vpn_connection_tunnel2_inside_ipv6_cidr" {
description = "(Optional) The range of inside IPv6 addresses for the second VPN tunnel. Supports only EC2 Transit Gateway. Valid value is a size /126 CIDR block from the local fd00::/8 range."
type = string
default = null
}
variable "vpn_connection_tunnel1_preshared_key" {
description = "(Optional) The preshared key of the first VPN tunnel. The preshared key must be between 8 and 64 characters in length and cannot start with zero(0). Allowed characters are alphanumeric characters, periods(.) and underscores(_)."
type = string
default = null
sensitive = true
}
variable "vpn_connection_tunnel2_preshared_key" {
description = " (Optional) The preshared key of the second VPN tunnel. The preshared key must be between 8 and 64 characters in length and cannot start with zero(0). Allowed characters are alphanumeric characters, periods(.) and underscores(_)."
type = string
default = null
sensitive = true
}
variable "vpn_connection_tunnel1_dpd_timeout_action" {
description = "(Optional, Default clear) The action to take after DPD timeout occurs for the first VPN tunnel. Specify restart to restart the IKE initiation. Specify clear to end the IKE session. Valid values are clear | none | restart."
type = string
default = "clear"
validation {
condition = can(regex("^(clear|none|restart)$", var.vpn_connection_tunnel1_dpd_timeout_action))
error_message = "Invalid input, options: \"clear\", \"none\", \"restart\"."
}
}
variable "vpn_connection_tunnel2_dpd_timeout_action" {
description = "(Optional, Default clear) The action to take after DPD timeout occurs for the second VPN tunnel. Specify restart to restart the IKE initiation. Specify clear to end the IKE session. Valid values are clear | none | restart."
type = string
default = "clear"
validation {
condition = can(regex("^(clear|none|restart)$", var.vpn_connection_tunnel2_dpd_timeout_action))
error_message = "Invalid input, options: \"clear\", \"none\", \"restart\"."
}
}
variable "vpn_connection_tunnel1_dpd_timeout_seconds" {
description = "(Optional, Default 30) The number of seconds after which a DPD timeout occurs for the second VPN tunnel. Valid value is equal or higher than 30."
type = number
default = 30
}
variable "vpn_connection_tunnel2_dpd_timeout_seconds" {
description = "(Optional, Default 30) The number of seconds after which a DPD timeout occurs for the second VPN tunnel. Valid value is equal or higher than 30."
type = string
default = 30
}
variable "vpn_connection_tunnel1_ike_versions" {
description = "(Optional) The IKE versions that are permitted for the first VPN tunnel. Valid values are ikev1 | ikev2."
type = set(string)
default = [null]
validation {
condition = can([for i in var.vpn_connection_tunnel1_ike_versions : regex("^(ikev1|ikev2)$", i)])
error_message = "Invalid input, options: \"ikev1\",\"ikev2\"."
}
}
variable "vpn_connection_tunnel2_ike_versions" {
description = "(Optional) The IKE versions that are permitted for the first VPN tunnel. Valid values are ikev1 | ikev2."
type = set(string)
default = [null]
validation {
condition = can([for i in var.vpn_connection_tunnel2_ike_versions : regex("^(ikev1|ikev2)$", i)])
error_message = "Invalid input, options: \"ikev1\",\"ikev2\"."
}
}
variable "tunnel1_log_options" {
description = "(Optional) Options for logging VPN tunnel activity. "
type = list(object({
log_enabled = bool # (Optional) Enable or disable VPN tunnel logging feature. The default is false.
log_group_arn = string # (Optional) The Amazon Resource Name (ARN) of the CloudWatch log group to send logs to.
log_output_format = string # (Optional) Set log format. Default format is json. Possible values are: json and text. The default is json.
}))
default = []
validation {
condition = can(regex("^(json|text)$", var.tunnel1_log_options[0].log_output_format))
error_message = "Invalid input, options: \"json\",\"text\"."
}
}
variable "tunnel2_log_options" {
description = "(Optional) Options for logging VPN tunnel activity. "
type = list(object({
log_enabled = bool # (Optional) Enable or disable VPN tunnel logging feature. The default is false.
log_group_arn = string # (Optional) The Amazon Resource Name (ARN) of the CloudWatch log group to send logs to.
log_output_format = string # (Optional) Set log format. Default format is json. Possible values are: json and text. The default is json.
}))
default = []
validation {
condition = can(regex("^(json|text)$", var.tunnel2_log_options[0].log_output_format))
error_message = "Invalid input, options: \"json\",\"text\"."
}
}
variable "vpn_connection_tunnel1_phase1_dh_group_numbers" {
description = "(Optional) List of one or more Diffie-Hellman group numbers that are permitted for the first VPN tunnel for phase 1 IKE negotiations. Valid values are 2 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24."
type = set(number)
default = [2,14,15,16,17,18,19,20,21,22,23,24]
validation {
condition = can([for i in var.vpn_connection_tunnel1_phase1_dh_group_numbers : regex("^(2|14|15|16|17|18|19|20|21|22|23|24)$", i)])
error_message = "Invalid input, options: \"2|14|15|16|17|18|19|20|21|22|23|24\"."
}
}
variable "vpn_connection_tunnel2_phase1_dh_group_numbers" {
description = "(Optional) List of one or more Diffie-Hellman group numbers that are permitted for the second VPN tunnel for phase 1 IKE negotiations. Valid values are 2 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24."
type = set(number)
default = [2,14,15,16,17,18,19,20,21,22,23,24]
validation {
condition = can([for i in var.vpn_connection_tunnel2_phase1_dh_group_numbers : regex("^(2|14|15|16|17|18|19|20|21|22|23|24)$", i)])
error_message = "Invalid input, options: \"2|14|15|16|17|18|19|20|21|22|23|24\"."
}
}
variable "vpn_connection_tunnel1_phase1_encryption_algorithms" {
description = "(Optional) List of one or more encryption algorithms that are permitted for the first VPN tunnel for phase 1 IKE negotiations. Valid values are AES128 | AES256 | AES128-GCM-16 | AES256-GCM-16."
type = set(string)
default = ["AES128","AES256","AES128-GCM-16","AES256-GCM-16"]
validation {
condition = can([for i in var.vpn_connection_tunnel1_phase1_encryption_algorithms : regex("^(AES128|AES256|AES128-GCM-16|AES256-GCM-16)$", i)])
error_message = "Invalid input, options: \"AES128|AES256|AES128-GCM-16|AES256-GCM-16\"."
}
}
variable "vpn_connection_tunnel2_phase1_encryption_algorithms" {
description = "(Optional) List of one or more encryption algorithms that are permitted for the second VPN tunnel for phase 1 IKE negotiations. Valid values are AES128 | AES256 | AES128-GCM-16 | AES256-GCM-16."
type = set(string)
default = ["AES128","AES256","AES128-GCM-16","AES256-GCM-16"]
validation {
condition = can([for i in var.vpn_connection_tunnel2_phase1_encryption_algorithms : regex("^(AES128|AES256|AES128-GCM-16|AES256-GCM-16)$", i)])
error_message = "Invalid input, options: \"AES128|AES256|AES128-GCM-16|AES256-GCM-16\"."
}
}
variable "vpn_connection_tunnel1_phase1_integrity_algorithms" {
description = "(Optional) One or more integrity algorithms that are permitted for the first VPN tunnel for phase 1 IKE negotiations. Valid values are SHA1 | SHA2-256 | SHA2-384 | SHA2-512."
type = set(string)
default = ["SHA1","SHA2-256","SHA2-384","SHA2-512"]
validation {
condition = can([for i in var.vpn_connection_tunnel1_phase1_integrity_algorithms : regex("^(SHA1|SHA2-256|SHA2-384|SHA2-512)$", i)])
error_message = "Invalid input, options: \"SHA1|SHA2-256|SHA2-384|SHA2-512\"."
}
}
variable "vpn_connection_tunnel2_phase1_integrity_algorithms" {
description = "(Optional) One or more integrity algorithms that are permitted for the second VPN tunnel for phase 1 IKE negotiations. Valid values are SHA1 | SHA2-256 | SHA2-384 | SHA2-512."
type = set(string)
default = ["SHA1","SHA2-256","SHA2-384","SHA2-512"]
validation {
condition = can([for i in var.vpn_connection_tunnel2_phase1_integrity_algorithms : regex("^(SHA1|SHA2-256|SHA2-384|SHA2-512)$", i)])
error_message = "Invalid input, options: \"SHA1|SHA2-256|SHA2-384|SHA2-512\"."
}
}
variable "vpn_connection_tunnel1_phase1_lifetime_seconds" {
description = " (Optional, Default 28800) The lifetime for phase 1 of the IKE negotiation for the first VPN tunnel, in seconds. Valid value is between 900 and 28800."
type = number
default = 28800
validation {
condition = var.vpn_connection_tunnel1_phase1_lifetime_seconds <= 28800 && var.vpn_connection_tunnel1_phase1_lifetime_seconds >= 900
error_message = "Invalid input, options: Valid value is between 900 and 28800."
}
}
variable "vpn_connection_tunnel2_phase1_lifetime_seconds" {
description = "(Optional, Default 28800) The lifetime for phase 1 of the IKE negotiation for the second VPN tunnel, in seconds. Valid value is between 900 and 28800."
type = number
default = 28800
validation {
condition = var.vpn_connection_tunnel2_phase1_lifetime_seconds <= 28800 && var.vpn_connection_tunnel2_phase1_lifetime_seconds >= 900
error_message = "Invalid input, options: Valid value is between 900 and 28800."
}
}
variable "vpn_connection_tunnel2_phase2_dh_group_numbers" {
description = "(Optional) List of one or more Diffie-Hellman group numbers that are permitted for the second VPN tunnel for phase 2 IKE negotiations. Valid values are 2 | 5 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24."
type = set(number)
default = [2,5,14,15,16,17,18,19,20,21,22,23,24]
validation {
condition = can([for i in var.vpn_connection_tunnel2_phase2_dh_group_numbers : regex("^(2|5|14|15|16|17|18|19|20|21|22|23|24)$", i)])
error_message = "Invalid input, options: \"2|5|14|15|16|17|18|19|20|21|22|23|24\"."
}
}
variable "vpn_connection_tunnel1_phase2_dh_group_numbers" {
description = "(Optional) List of one or more Diffie-Hellman group numbers that are permitted for the first VPN tunnel for phase 2 IKE negotiations. Valid values are 2 | 5 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24."
type = set(number)
default = [2,5,14,15,16,17,18,19,20,21,22,23,24]
validation {
condition = can([for i in var.vpn_connection_tunnel1_phase2_dh_group_numbers : regex("^(2|5|14|15|16|17|18|19|20|21|22|23|24)$", i)])
error_message = "Invalid input, options: \"2|5|14|15|16|17|18|19|20|21|22|23|24\"."
}
}
variable "vpn_connection_tunnel1_phase2_encryption_algorithms" {
description = " (Optional) List of one or more encryption algorithms that are permitted for the first VPN tunnel for phase 2 IKE negotiations. Valid values are AES128 | AES256 | AES128-GCM-16 | AES256-GCM-16."
type = list(string)
default = ["AES128", "AES256", "AES128-GCM-16", "AES256-GCM-16"]
validation {
condition = can([for i in var.vpn_connection_tunnel1_phase2_encryption_algorithms : regex("^(AES128|AES256|AES128-GCM-16|AES256-GCM-16)$", i)])
error_message = "Invalid input, options: \"AES128|AES256|AES128-GCM-16|AES256-GCM-16\"."
}
}
variable "vpn_connection_tunnel2_phase2_encryption_algorithms" {
description = "(Optional) List of one or more encryption algorithms that are permitted for the second VPN tunnel for phase 2 IKE negotiations. Valid values are AES128 | AES256 | AES128-GCM-16 | AES256-GCM-16."
type = list(string)
default = ["AES128", "AES256", "AES128-GCM-16", "AES256-GCM-16"]
validation {
condition = can([for i in var.vpn_connection_tunnel2_phase2_encryption_algorithms : regex("^(AES128|AES256|AES128-GCM-16|AES256-GCM-16)$", i)])
error_message = "Invalid input, options: \"AES128|AES256|AES128-GCM-16|AES256-GCM-16\"."
}
}
variable "vpn_connection_tunnel1_phase2_integrity_algorithms" {
description = "(Optional) List of one or more integrity algorithms that are permitted for the first VPN tunnel for phase 2 IKE negotiations. Valid values are SHA1 | SHA2-256 | SHA2-384 | SHA2-512."
type = list(string)
default = ["SHA1","SHA2-256","SHA2-384","SHA2-512"]
validation {
condition = can([for i in var.vpn_connection_tunnel1_phase2_integrity_algorithms : regex("^(SHA1|SHA2-256|SHA2-384|SHA2-512)$", i)])
error_message = "Invalid input, options: \"SHA1|SHA2-256|SHA2-384|SHA2-512\"."
}
}
variable "vpn_connection_tunnel2_phase2_integrity_algorithms" {
description = "(Optional) List of one or more integrity algorithms that are permitted for the second VPN tunnel for phase 2 IKE negotiations. Valid values are SHA1 | SHA2-256 | SHA2-384 | SHA2-512."
type = list(string)
default = ["SHA1","SHA2-256","SHA2-384","SHA2-512"]
validation {
condition = can([for i in var.vpn_connection_tunnel2_phase2_integrity_algorithms : regex("^(SHA1|SHA2-256|SHA2-384|SHA2-512)$", i)])
error_message = "Invalid input, options: \"SHA1|SHA2-256|SHA2-384|SHA2-512\"."
}
}
variable "vpn_connection_tunnel1_phase2_lifetime_seconds" {
description = " (Optional, Default 3600) The lifetime for phase 2 of the IKE negotiation for the first VPN tunnel, in seconds. Valid value is between 900 and 3600."
type = number
default = 3600
validation {
condition = var.vpn_connection_tunnel1_phase2_lifetime_seconds <= 3600 && var.vpn_connection_tunnel1_phase2_lifetime_seconds >= 900 || var.vpn_connection_tunnel1_phase2_lifetime_seconds == null
error_message = "Invalid input, options: Valid value is between 900 and 3600."
}
}
variable "vpn_connection_tunnel2_phase2_lifetime_seconds" {
description = "(Optional, Default 3600) The lifetime for phase 2 of the IKE negotiation for the second VPN tunnel, in seconds. Valid value is between 900 and 3600."
type = number
default = 3600
validation {
condition = var.vpn_connection_tunnel2_phase2_lifetime_seconds <= 3600 && var.vpn_connection_tunnel2_phase2_lifetime_seconds >= 900 || var.vpn_connection_tunnel2_phase2_lifetime_seconds == null
error_message = "Invalid input, options: Valid value is between 900 and 3600."
}
}
variable "vpn_connection_tunnel1_rekey_fuzz_percentage" {
description = "(Optional, Default 100) The percentage of the rekey window for the first VPN tunnel (determined by tunnel1_rekey_margin_time_seconds) during which the rekey time is randomly selected. Valid value is between 0 and 100."
type = number
default = 100
validation {
condition = var.vpn_connection_tunnel1_rekey_fuzz_percentage <= 100 && var.vpn_connection_tunnel1_rekey_fuzz_percentage >= 0
error_message = "Invalid input, options: Valid value is between 0 and 100."
}
}
variable "vpn_connection_tunnel2_rekey_fuzz_percentage" {
description = "(Optional, Default 100) The percentage of the rekey window for the second VPN tunnel (determined by tunnel2_rekey_margin_time_seconds) during which the rekey time is randomly selected. Valid value is between 0 and 100."
type = number
default = 100
validation {
condition = var.vpn_connection_tunnel2_rekey_fuzz_percentage <= 100 && var.vpn_connection_tunnel2_rekey_fuzz_percentage >= 0
error_message = "Invalid input, options: Valid value is between 0 and 100."
}
}
variable "vpn_connection_tunnel1_rekey_margin_time_seconds" {
description = "(Optional, Default 540) The margin time, in seconds, before the phase 2 lifetime expires, during which the AWS side of the first VPN connection performs an IKE rekey. The exact time of the rekey is randomly selected based on the value for tunnel1_rekey_fuzz_percentage. Valid value is between 60 and half of tunnel1_phase2_lifetime_seconds."
type = number
default = 540
}
variable "vpn_connection_tunnel2_rekey_margin_time_seconds" {
description = "(Optional, Default 540) The margin time, in seconds, before the phase 2 lifetime expires, during which the AWS side of the second VPN connection performs an IKE rekey. The exact time of the rekey is randomly selected based on the value for tunnel2_rekey_fuzz_percentage. Valid value is between 60 and half of tunnel2_phase2_lifetime_seconds."
type = number
default = 540
}
variable "vpn_connection_tunnel1_replay_window_size" {
description = "(Optional, Default 1024) The number of packets in an IKE replay window for the first VPN tunnel. Valid value is between 64 and 2048."
type = number
default = 1024
validation {
condition = var.vpn_connection_tunnel1_replay_window_size <= 2048 && var.vpn_connection_tunnel1_replay_window_size >= 64
error_message = "Invalid input, options: Valid value is between 64 and 2048."
}
}
variable "vpn_connection_tunnel2_replay_window_size" {
description = "(Optional, Default 1024) The number of packets in an IKE replay window for the second VPN tunnel. Valid value is between 64 and 2048."
type = number
default = 1024
validation {
condition = var.vpn_connection_tunnel2_replay_window_size <= 2048 && var.vpn_connection_tunnel2_replay_window_size >= 64
error_message = "Invalid input, options: Valid value is between 64 and 2048."
}
}
variable "vpn_connection_tunnel1_startup_action" {
description = "(Optional, Default add) The action to take when the establishing the tunnel for the first VPN connection. By default, your customer gateway device must initiate the IKE negotiation and bring up the tunnel. Specify start for AWS to initiate the IKE negotiation. Valid values are add | start."
type = string
validation {
condition = can(regex("^(add|start)$", var.vpn_connection_tunnel1_startup_action))
error_message = "Invalid input, options: \"add|start\"."
}
}
variable "vpn_connection_tunnel2_startup_action" {
description = "(Optional, Default add) The action to take when the establishing the tunnel for the second VPN connection. By default, your customer gateway device must initiate the IKE negotiation and bring up the tunnel. Specify start for AWS to initiate the IKE negotiation. Valid values are add | start."
type = string
validation {
condition = can(regex("^(add|start)$", var.vpn_connection_tunnel2_startup_action))
error_message = "Invalid input, options: \"add|start\"."
}
}

variable "vpn_connection_route_destination_cidr_block" {
description = "(Required) The CIDR block associated with the local subnet of the customer network."
type = list(string)
}

Next terraform.tfvars file

customer_gateway_bgp_asn = 65000
customer_gateway_ip_address = "172.83.124.10"
customer_gateway_type = "ipsec.1" #(Required) The only type AWS supports at this time is ipsec.1
# customer_gateway_certificate_arn = "arn:aws:acm:ap-southeast-1:111111111111:certificate/365ac088-d023-4690-aa8e-6e4831a73332"
customer_gateway_device_name = "demo_customer_gateway"
tags = {
"Name" = "demo_customer_gateway"
}
virtual_private_gateways_vpc_id = "vpc-0421b67782c4a7158"
# # virtual_private_gateways_amazon_side_asn = 65001
# virtual_private_gateways_availability_zone = "ap-southeast-1a"
route_propagation_route_table_ids = ["rtb-033562682aace18be"]
vpn_connection_static_routes_only = true # Static routes must be used for devices that don't support BGP.
vpn_connection_local_ipv4_network_cidr = "0.0.0.0/0"
vpn_connection_outside_ip_address_type = "PublicIpv4"
vpn_connection_remote_ipv4_network_cidr = "0.0.0.0/0"

#####EC2 Transit Gateway
vpn_connection_transit_gateway_id = "tgw-0db1d860e7546e914"
vpn_connection_local_ipv6_network_cidr = "::/0"
vpn_connection_remote_ipv6_network_cidr = "::/0"
vpn_connection_tunnel1_inside_ipv6_cidr = "fd00::/126"
vpn_connection_tunnel2_inside_ipv6_cidr = "fd00:1::/126"
vpn_connection_enable_acceleration = true # Supports only EC2 Transit Gateway.
# vpn_connection_transport_transit_gateway_attachment_id = 

##vpn_connection_tunnel
vpn_connection_tunnel_inside_ip_version = "ipv6"
# vpn_connection_tunnel1_inside_cidr = "169.254.253.152/30"
# vpn_connection_tunnel2_inside_cidr = "169.254.116.244/30"
vpn_connection_tunnel1_dpd_timeout_action = "clear"
vpn_connection_tunnel2_dpd_timeout_action = "clear"
vpn_connection_tunnel1_ike_versions = ["ikev1"]
vpn_connection_tunnel2_ike_versions = ["ikev2"]
tunnel1_log_options = [{
log_enabled = true
log_group_arn = "arn:aws:logs:ap-southeast-1:111111111111:log-group:demo_vpn_loggroup:*"
log_output_format = "text"
}]
tunnel2_log_options = [{
log_enabled = true
log_group_arn = "arn:aws:logs:ap-southeast-1:111111111111:log-group:demo_vpn_loggroup:*"
log_output_format = "json"
}]
vpn_connection_tunnel1_phase1_dh_group_numbers = [2]
vpn_connection_tunnel1_phase1_integrity_algorithms = ["SHA2-256"]
vpn_connection_tunnel1_phase1_encryption_algorithms = ["AES128"]
vpn_connection_tunnel1_phase2_dh_group_numbers = ["2"]
vpn_connection_tunnel2_phase1_dh_group_numbers = [2]
vpn_connection_tunnel2_phase1_integrity_algorithms = ["SHA2-256"]
vpn_connection_tunnel2_phase1_encryption_algorithms = ["AES128"]
vpn_connection_tunnel1_phase1_lifetime_seconds = 1000
vpn_connection_tunnel2_phase1_lifetime_seconds = 1000
vpn_connection_tunnel2_phase2_dh_group_numbers = ["2"]
vpn_connection_tunnel1_phase2_encryption_algorithms = ["AES128"]
vpn_connection_tunnel2_phase2_encryption_algorithms = ["AES128"]
vpn_connection_tunnel1_phase2_integrity_algorithms = ["SHA2-256"]
vpn_connection_tunnel2_phase2_integrity_algorithms = ["SHA2-256"]
vpn_connection_tunnel1_phase2_lifetime_seconds = 1000
vpn_connection_tunnel2_phase2_lifetime_seconds = 1000
vpn_connection_tunnel1_rekey_fuzz_percentage = 100
vpn_connection_tunnel2_rekey_fuzz_percentage = 100
vpn_connection_tunnel1_rekey_margin_time_seconds = 60
vpn_connection_tunnel2_rekey_margin_time_seconds = 60
vpn_connection_tunnel1_replay_window_size = 64
vpn_connection_tunnel2_replay_window_size = 64
vpn_connection_tunnel1_startup_action = "add"
vpn_connection_tunnel2_startup_action = "add"

# vpn_connection_static_route
vpn_connection_route_destination_cidr_block = ["192.168.10.0/24", "192.168.20.0/24", "192.168.30.0/24"]

I hope this article help you. Happy Learning !!!