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 +} +