diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5266857..5b0ff65 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -310,3 +310,9 @@
- use default retention of 6 months, allow it as a variable
- examples/full-setup-tf-upgrade
- change vpc-endpoints to be in subdirectory, by default use all endpoints, and no local endpoints
+
+* 2.9.0 -- 2023-05-26
+ - vpn-transit-gateway
+ - new variables for creating cloudwatch alarms
+ - create_cloudwatch_alarms
+ - cloudwatch_alarm_topic_arn
diff --git a/common/version.tf b/common/version.tf
index f031e1a..6c29bd1 100644
--- a/common/version.tf
+++ b/common/version.tf
@@ -1,5 +1,5 @@
locals {
- _module_version = "2.8.3"
+ _module_version = "2.9.0"
_module_names = {
"_main_" = "aws-vpc-setup"
@@ -23,7 +23,6 @@ locals {
"vpc-interface-endpoint" = "aws-vpc-setup/vpc-interface-endpoint"
"vpn" = "aws-vpc-setup/vpn"
"vpn-transit-gateway" = "aws-vpc-setup/vpn-transit-gateway"
- "vpn-transit-gateway" = "aws-vpc-setup/vpn-transit-gateway"
"vpc-transit-gateway-association/data" = "aws-vpc-setup/vpc-transit-gateway-association/data"
"vpc-transit-gateway-association/self" = "aws-vpc-setup/vpc-transit-gateway-association/self"
"vpc-transit-gateway-association/peer" = "aws-vpc-setup/vpc-transit-gateway-association/peer"
diff --git a/vpn-transit-gateway/README.md b/vpn-transit-gateway/README.md
index 1b59334..38d14e8 100644
--- a/vpn-transit-gateway/README.md
+++ b/vpn-transit-gateway/README.md
@@ -37,6 +37,8 @@ module "vpn_transit-gateway" {
# optional
# use_tgw_prefixes = true
+ # create_cloudwatch_alarms = true
+ # cloudwatch_alarm_topic_arn = data.aws_sns_topic.mytopic.arn
}
```
@@ -70,6 +72,7 @@ No modules.
| Name | Type |
|------|------|
| [aws_cloudwatch_log_group.log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource |
+| [aws_cloudwatch_metric_alarm.tgw_vpn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | resource |
| [aws_customer_gateway.vpn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/customer_gateway) | resource |
| [aws_customer_gateway.vpn_single](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/customer_gateway) | resource |
| [aws_ec2_tag.vpn_tag_created_by](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_tag) | resource |
@@ -98,7 +101,9 @@ No modules.
|------|-------------|------|---------|:--------:|
| [account\_alias](#input\_account\_alias) | AWS Account Alias (default: will pull from current account\_alias) | `string` | `""` | no |
| [account\_id](#input\_account\_id) | AWS Account ID (default: will pull from current user) | `string` | `""` | no |
+| [cloudwatch\_alarm\_topic\_arn](#input\_cloudwatch\_alarm\_topic\_arn) | SNS ARN for Cloudwtch Metric Alarms for VPN tunnels. If null, no alarms will be created. | `string` | `null` | no |
| [create](#input\_create) | Flag to indicate whether to create the resources or not (default: true) | `bool` | `true` | no |
+| [create\_cloudwatch\_alarms](#input\_create\_cloudwatch\_alarms) | Flag to enable or disable creation of Cloudwatch Metric Alarms for VPN tunnels (requires cloudwatch\_alarm\_topic\_arn to be defined). | `bool` | n/a | yes |
| [enable\_cloudwatch\_logging](#input\_enable\_cloudwatch\_logging) | Flag to enable or disable VPN tunnel logging to CloudWatch. If Enabled, it will create the cloudwatch log groups | `bool` | `false` | no |
| [generate\_json\_files](#input\_generate\_json\_files) | Flag to enable or disable generation of JSON file from VPN information | `bool` | `false` | no |
| [generate\_yaml\_files](#input\_generate\_yaml\_files) | Flag to enable or disable generation of YAML file from VPN information | `bool` | `true` | no |
diff --git a/vpn-transit-gateway/cloudwatch_alarms.tf b/vpn-transit-gateway/cloudwatch_alarms.tf
new file mode 100644
index 0000000..764d2d4
--- /dev/null
+++ b/vpn-transit-gateway/cloudwatch_alarms.tf
@@ -0,0 +1,76 @@
+#data "aws_sns_topic" "tgw_vpn" {
+# name = format("inf-tgw-%v", local.region)
+#}
+
+locals {
+ vpn_t1_details = { for k, v in local.vpn_tunnel_outputs : format("%v:1", k) => {
+ tunnel_number = 1
+ name = format("%v-tunnel-%v.%v.%v", v.label, 1, v.account_alias, v.region)
+ account_alias = v.account_alias
+ account_id = v.account_id
+ customer_address = v.customer_address
+ full_label = v.full_label
+ label = v.label
+ region = v.region
+ sequence = v.sequence
+ site = v.site
+ tunnel_address = v.tunnel1_address
+ interface_number = v.tunnel1_interface_number
+ tunnel_label = v.tunnel1_label
+ loopback = v.tunnel1_loopback
+ vpc_id = local.vpc_id
+ cidr_block = v.vpc_cidr_block
+ vpc_short_name = v.vpc_short_name
+ vpc_name = v.vpc_name
+ vpn_environment = v.vpn_environment
+ vpn_connection_id = v.vpn_connection_id
+ } }
+ vpn_t2_details = { for k, v in local.vpn_tunnel_outputs : format("%v:2", k) => {
+ tunnel_number = 2
+ name = format("%v-tunnel-%v.%v.%v", v.label, 2, v.account_alias, v.region)
+ account_alias = v.account_alias
+ account_id = v.account_id
+ customer_address = v.customer_address
+ full_label = v.full_label
+ label = v.label
+ region = v.region
+ sequence = v.sequence
+ site = v.site
+ tunnel_address = v.tunnel2_address
+ interface_number = v.tunnel2_interface_number
+ tunnel_label = v.tunnel2_label
+ loopback = v.tunnel2_loopback
+ vpc_id = local.vpc_id
+ cidr_block = v.vpc_cidr_block
+ vpc_short_name = v.vpc_short_name
+ vpc_name = v.vpc_name
+ vpn_environment = v.vpn_environment
+ vpn_connection_id = v.vpn_connection_id
+ } }
+ vpn_details = merge(local.vpn_t1_details, local.vpn_t2_details)
+}
+
+resource "aws_cloudwatch_metric_alarm" "tgw_vpn" {
+ for_each = var.create_cloudwatch_alarms && var.cloudwatch_alarm_topic_arn != null ? local.vpn_details : {}
+ actions_enabled = true
+ alarm_actions = [var.cloudwatch_alarm_topic_arn]
+ alarm_description = templatefile("${path.module}/templates/cloudwatch_alarm.tpl", tomap(each.value))
+ alarm_name = each.value.name
+ comparison_operator = "LessThanThreshold"
+ datapoints_to_alarm = 5
+ dimensions = {
+ "TunnelIpAddress" = each.value.tunnel_address
+ }
+ evaluation_periods = 8
+ metric_name = "TunnelState"
+ namespace = "AWS/VPN"
+ period = 60
+ statistic = "Average"
+ threshold = 1
+ treat_missing_data = "missing"
+
+ tags = merge(
+ local.base_tags,
+ var.tags,
+ )
+}
diff --git a/vpn-transit-gateway/main.tf b/vpn-transit-gateway/main.tf
index 7e237bc..73b73a6 100644
--- a/vpn-transit-gateway/main.tf
+++ b/vpn-transit-gateway/main.tf
@@ -38,6 +38,8 @@
*
* # optional
* # use_tgw_prefixes = true
+* # create_cloudwatch_alarms = true
+* # cloudwatch_alarm_topic_arn = data.aws_sns_topic.mytopic.arn
* }
* ```
*/
diff --git a/vpn-transit-gateway/templates/cloudwatch_alarm.tpl b/vpn-transit-gateway/templates/cloudwatch_alarm.tpl
new file mode 100644
index 0000000..68a2e1d
--- /dev/null
+++ b/vpn-transit-gateway/templates/cloudwatch_alarm.tpl
@@ -0,0 +1,25 @@
+
+# VPN Tunnel Down
+
+## ${account_alias} ${region} ${label} tunnel ${tunnel_number}
+
+* account = ${account_alias} {account_id}
+* region = ${region}
+* label = ${full_label}
+* vpc
+ * id = ${vpc_id}
+ * cidr_block = ${cidr_block}
+ * name = ${vpc_short_name}-${vpc_name}
+* vpn_connection = ${vpn_connection_id}
+* tunnel
+ * site = ${site}
+ * environment = ${vpn_environment}
+ * sequence = ${sequence}
+* addresses
+ * tunnel_number = ${tunnel_number}
+ * tunnel_address = ${tunnel_address}
+ * tunnel_label = ${tunnel_label}
+ * interface_number = ${interface_number}
+ * loopback = ${loopback}
+ * asr-endpiont = ${customer_address}
+
diff --git a/vpn-transit-gateway/templates/global.yml.tmpl b/vpn-transit-gateway/templates/global.yml.tmpl
new file mode 100644
index 0000000..ee707e9
--- /dev/null
+++ b/vpn-transit-gateway/templates/global.yml.tmpl
@@ -0,0 +1,80 @@
+vrf: ${vrf}
+cloud_provider: aws
+aws:
+ region_full: ${region_full}
+ region_short: ${region_short}
+ vpc_full_name: ${vpc_full_name}
+ vpc_suffix: ${vpc_name}
+ vpc_number: ${vpc_number}
+ vpc_cidr_block: ${vpc_cidr_block}
+ vpn_connection_id: ${vpn_connection_id}
+ vpn_connection_description: ${vpn_connection_description}
+ tunnels:
+ - tunnel1:
+ description: ${vpc_connection_description}
+%{ for k,v in tunnel1 }
+ ${k}: ${v}
+%{ endfor ~}
+ - tunnel2:
+ description: ${vpc_connection_description}
+%{ for k,v in tunnel2 }
+ ${k}: ${v}
+%{ endfor ~}
+
+## tunnel1_bgp_asn = aws_vpn_connection.vpn[k].tunnel1_bgp_asn
+## tunnel1_address = aws_vpn_connection.vpn[k].tunnel1_address
+## tunnel1_inside_cidr = aws_vpn_connection.vpn[k].tunnel1_inside_cidr
+## tunnel1_cgw_inside_address = aws_vpn_connection.vpn[k].tunnel1_cgw_inside_address
+## tunnel1_vgw_inside_address = aws_vpn_connection.vpn[k].tunnel1_vgw_inside_address
+##
+
+asr:
+ site: ${site}
+# device_name: hqnt-r1-cld-vpn-rtr1
+ device_name: bccm2-dmz-r68-cld-vpn-rtr1
+
+
+
+
+aws:
+ region: us-gov-east-1 | us-gov-west-1
+# description: (none)
+# comment: for EW, we will need 4 new BGP numbers, one per region east-1, east-2, west-1, west-2
+ region_short: east | west
+# description: AWS VPC Region
+ vpc_name: vpc1-tgw-common | vpc2-dice-dev | ..
+# description: AWS VPC Name
+ vpc_short_name: vpc1
+# description: AWS VPC Sub-name
+ vpc_number: 1 | 2 | ...
+# description: AWS VPC Number
+ vrf_name: cen-services | cen-dev | cen-test | cen-stage | cen-prod | cen-cre | misc-dmz
+# description: VRF Name (ALL CAPS)
+ vpn_connection_id:
+# comment: not sure how to represent this just yet
+# description: AWS VPN Connection ID BCC: [BCC ID]
+# description: AWS VPN Connection ID HQ: [HQ ID]
+ aws_bgp_asn: 64513 (east) | 64514 (west)
+# description: AWS BGP ASN
+
+## from TCO
+asr:
+ tunnel_interface_numbers: [ tu-1-number, tu-2-number ]
+# description: Tunnel 1 Interface Number
+# description: Tunnel 2 Interface Number
+ tunnel_interface_prefixes:
+# description: map of VRF to prefix of {prefix}{xx}
+ cen-dev: 14
+ cen-test: 15
+ cen-stage: 16
+ cen-prod: 17
+ cen-service: 18
+ cen-cre: 19
+ misc-dmz: 99
+ loopback_number: {integer}
+# description: Loopback Number
+ object_track_interface_numbers: [ tu-1-number-drop-leading-digit, tu-2-number-drop-leading-digit ]
+# description: Object Track 1: [TRACK 1]
+# description: Object Track 2: [TRACK 2]
+# comment: Drop 1st digit of Tu interface
+# comment: not sure how that works with misc-dmz
diff --git a/vpn-transit-gateway/variables.tf b/vpn-transit-gateway/variables.tf
index 9445bb3..ec8033d 100644
--- a/vpn-transit-gateway/variables.tf
+++ b/vpn-transit-gateway/variables.tf
@@ -86,3 +86,16 @@ variable "use_single_cgw" {
type = bool
default = false
}
+
+variable "create_cloudwatch_alarms" {
+ description = "Flag to enable or disable creation of Cloudwatch Metric Alarms for VPN tunnels (requires cloudwatch_alarm_topic_arn to be defined)."
+ type = bool
+ defualt = true
+}
+
+variable "cloudwatch_alarm_topic_arn" {
+ description = "SNS ARN for Cloudwtch Metric Alarms for VPN tunnels. If null, no alarms will be created."
+ type = string
+ default = null
+}
+