Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactors vpn connection module to support all options and targets #310

Merged
merged 6 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 2.0.0
current_version = 3.0.0
commit = True
message = Bumps version to {new_version}
tag = False
Expand Down
50 changes: 25 additions & 25 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
- package-ecosystem: docker
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: terraform
directory: "/tests/create_vpn_gateway"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: terraform
directory: "/tests/create_customer_gateway"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: terraform
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
# Maintain dependencies for GitHub Actions
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
- package-ecosystem: docker
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: terraform
directory: "/tests/create_vpn_gateway"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: terraform
directory: "/tests/create_vpn_gateway_with_connections"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: terraform
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ jobs:
uses: plus3it/actions-workflows/.github/workflows/release.yml@c9c3d1193bd64bc2a9def11605608a98a3164d96
secrets:
release-token: ${{ secrets.GH_RELEASES_TOKEN }}
with:
mockstacktest-enable: false
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).

### 3.0.0

**Released**: 2023.12.09

**Commit Delta**: [Change from 1.0.2 release](https://github.com/plus3it/terraform-aws-tardigrade-vpn-connection/compare/1.0.2...3.0.0)

**Summary**:

* Completely refactors module to support all VPN Connection options and target
types, including VPN Gateway and Transit Gateway

### 1.0.2

**Released**: 2019.10.28
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
FROM plus3it/tardigrade-ci:0.24.6
FROM plus3it/tardigrade-ci:0.24.15
18 changes: 4 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# terraform-aws-tardigrade-vpn-connection

Terraform module to create a VPN Connection
Terraform module to manage a VPN Connection

## Testing

Expand Down Expand Up @@ -42,23 +42,13 @@ make mockstack/clean

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_amazon_side_asn"></a> [amazon\_side\_asn](#input\_amazon\_side\_asn) | ASN for the Amazon side of the VPN gateway | `string` | `"64512"` | no |
| <a name="input_cgw_bgp_asn"></a> [cgw\_bgp\_asn](#input\_cgw\_bgp\_asn) | BGP ASN of the customer gateway | `string` | `null` | no |
| <a name="input_cgw_ip_addresses"></a> [cgw\_ip\_addresses](#input\_cgw\_ip\_addresses) | List of IP addresses of the customer gateways | `list(string)` | `[]` | no |
| <a name="input_destination_cidr_blocks"></a> [destination\_cidr\_blocks](#input\_destination\_cidr\_blocks) | List of CIDR blocks to route through the VPN Connection | `list` | `[]` | no |
| <a name="input_name"></a> [name](#input\_name) | Name tag to associate to all resources that support tags | `string` | `null` | no |
| <a name="input_propagating_route_table_count"></a> [propagating\_route\_table\_count](#input\_propagating\_route\_table\_count) | Number of route tables in the list of progagating\_route\_table\_ids | `string` | `"0"` | no |
| <a name="input_propagating_route_table_ids"></a> [propagating\_route\_table\_ids](#input\_propagating\_route\_table\_ids) | List of Route Table IDs to propagate routes into, from the VPN Gateway | `list` | `[]` | no |
| <a name="input_static_routes_only"></a> [static\_routes\_only](#input\_static\_routes\_only) | Boolean used to determine whether the VPN connection uses static routes exclusively. Static routes must be used for devices that don't support BGP | `bool` | `"false"` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | A map of tags to add to any VPN resource that supports tags | `map(string)` | `{}` | no |
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | VPC ID to which the VPN Connection will be attached | `string` | `null` | no |
| <a name="input_vpn_connection"></a> [vpn\_connection](#input\_vpn\_connection) | n/a | <pre>object({<br> name = string<br> static_routes_only = optional(bool, false)<br> tags = optional(map(string), {})<br> type = optional(string, "ipsec.1")<br><br> transit_gateway_id = optional(string)<br> vpn_gateway_id = optional(string)<br><br> enable_acceleration = optional(bool)<br> outside_ip_address_type = optional(string)<br> transport_transit_gateway_attachment_id = optional(string)<br> tunnel_inside_ip_version = optional(string)<br><br> local_ipv4_network_cidr = optional(string)<br> local_ipv6_network_cidr = optional(string)<br><br> remote_ipv4_network_cidr = optional(string)<br> remote_ipv6_network_cidr = optional(string)<br><br> tunnel1_inside_cidr = optional(string)<br> tunnel1_inside_ipv6_cidr = optional(string)<br> tunnel1_preshared_key = optional(string)<br> tunnel1_dpd_timeout_action = optional(string)<br> tunnel1_dpd_timeout_seconds = optional(number)<br> tunnel1_enable_tunnel_lifecycle_control = optional(bool)<br> tunnel1_ike_versions = optional(list(string))<br> tunnel1_rekey_fuzz_percentage = optional(number)<br> tunnel1_rekey_margin_time_seconds = optional(number)<br> tunnel1_replay_window_size = optional(number)<br> tunnel1_startup_action = optional(string)<br><br> tunnel1_phase1_dh_group_numbers = optional(list(number))<br> tunnel1_phase1_encryption_algorithms = optional(list(string))<br> tunnel1_phase1_integrity_algorithms = optional(list(string))<br> tunnel1_phase1_lifetime_seconds = optional(number)<br><br> tunnel1_phase2_dh_group_numbers = optional(list(number))<br> tunnel1_phase2_encryption_algorithms = optional(list(string))<br> tunnel1_phase2_integrity_algorithms = optional(list(string))<br> tunnel1_phase2_lifetime_seconds = optional(number)<br><br> tunnel1_log_options = optional(object({<br> cloudwatch_log_options = optional(object({<br> log_group_arn = optional(string)<br> log_enabled = optional(bool, true)<br> log_output_format = optional(string, "json")<br> }), {})<br><br> cloudwatch_log_group = optional(object({<br> kms_key_id = optional(string)<br> log_group_class = optional(string, "INFREQUENT_ACCESS")<br> retention_in_days = optional(number, 30)<br> skip_destroy = optional(bool, false)<br> tags = optional(map(string), {})<br> }), {})<br> }), {})<br><br> tunnel2_inside_cidr = optional(string)<br> tunnel2_inside_ipv6_cidr = optional(string)<br> tunnel2_preshared_key = optional(string)<br> tunnel2_dpd_timeout_action = optional(string)<br> tunnel2_dpd_timeout_seconds = optional(number)<br> tunnel2_enable_tunnel_lifecycle_control = optional(bool)<br> tunnel2_ike_versions = optional(list(string))<br> tunnel2_rekey_fuzz_percentage = optional(number)<br> tunnel2_rekey_margin_time_seconds = optional(number)<br> tunnel2_replay_window_size = optional(number)<br> tunnel2_startup_action = optional(string)<br><br> tunnel2_phase1_dh_group_numbers = optional(list(number))<br> tunnel2_phase1_encryption_algorithms = optional(list(string))<br> tunnel2_phase1_integrity_algorithms = optional(list(string))<br> tunnel2_phase1_lifetime_seconds = optional(number)<br><br> tunnel2_phase2_dh_group_numbers = optional(list(number))<br> tunnel2_phase2_encryption_algorithms = optional(list(string))<br> tunnel2_phase2_integrity_algorithms = optional(list(string))<br> tunnel2_phase2_lifetime_seconds = optional(number)<br><br> tunnel2_log_options = optional(object({<br> cloudwatch_log_options = optional(object({<br> log_group_arn = optional(string)<br> log_enabled = optional(bool, true)<br> log_output_format = optional(string, "json")<br> }), {})<br><br> cloudwatch_log_group = optional(object({<br> kms_key_id = optional(string)<br> log_group_class = optional(string, "INFREQUENT_ACCESS")<br> retention_in_days = optional(number, 30)<br> skip_destroy = optional(bool, false)<br> tags = optional(map(string), {})<br> }), {})<br> }), {})<br><br> customer_gateway = object({<br> name = string<br> bgp_asn = string<br> certificate_arn = optional(string)<br> device_name = optional(string)<br> ip_address = optional(string)<br> tags = optional(map(string))<br> type = optional(string, "ipsec.1")<br> })<br><br> routes = optional(list(object({<br> name = string<br> destination_cidr_block = string<br> })), [])<br> })</pre> | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_customer_gateway_ids"></a> [customer\_gateway\_ids](#output\_customer\_gateway\_ids) | IDs of the Customer Gateways |
| <a name="output_vpn_connection_ids"></a> [vpn\_connection\_ids](#output\_vpn\_connection\_ids) | IDs of the VPN Connections |
| <a name="output_vpn_gateway_id"></a> [vpn\_gateway\_id](#output\_vpn\_gateway\_id) | ID of the VPN Gateway |
| <a name="output_customer_gateway"></a> [customer\_gateway](#output\_customer\_gateway) | Object of Customer Gateway attributes |
| <a name="output_vpn_connection"></a> [vpn\_connection](#output\_vpn\_connection) | Object of VPN Connection attributes |

<!-- END TFDOCS -->
158 changes: 122 additions & 36 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,60 +1,146 @@
locals {
vgw_name = var.name == null ? "VGW" : "VGW_${var.name}"
cgw_name = var.name == null ? "CGW" : "CGW_${var.name}"
vpn_name = var.name == null ? "VPN" : "VPN_${var.name}"
}
resource "aws_vpn_connection" "this" {
customer_gateway_id = aws_customer_gateway.this.id
static_routes_only = var.vpn_connection.static_routes_only
type = var.vpn_connection.type

transit_gateway_id = var.vpn_connection.transit_gateway_id
vpn_gateway_id = var.vpn_connection.vpn_gateway_id

enable_acceleration = var.vpn_connection.enable_acceleration
outside_ip_address_type = var.vpn_connection.outside_ip_address_type
transport_transit_gateway_attachment_id = var.vpn_connection.transport_transit_gateway_attachment_id
tunnel_inside_ip_version = var.vpn_connection.tunnel_inside_ip_version

local_ipv4_network_cidr = var.vpn_connection.local_ipv4_network_cidr
local_ipv6_network_cidr = var.vpn_connection.local_ipv6_network_cidr

remote_ipv4_network_cidr = var.vpn_connection.remote_ipv4_network_cidr
remote_ipv6_network_cidr = var.vpn_connection.remote_ipv6_network_cidr

tunnel1_inside_cidr = var.vpn_connection.tunnel1_inside_cidr
tunnel1_inside_ipv6_cidr = var.vpn_connection.tunnel1_inside_ipv6_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_enable_tunnel_lifecycle_control = var.vpn_connection.tunnel1_enable_tunnel_lifecycle_control
tunnel1_ike_versions = var.vpn_connection.tunnel1_ike_versions
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_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

tunnel2_inside_cidr = var.vpn_connection.tunnel2_inside_cidr
tunnel2_inside_ipv6_cidr = var.vpn_connection.tunnel2_inside_ipv6_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_enable_tunnel_lifecycle_control = var.vpn_connection.tunnel2_enable_tunnel_lifecycle_control
tunnel2_ike_versions = var.vpn_connection.tunnel2_ike_versions
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_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

dynamic "tunnel1_log_options" {
for_each = var.vpn_connection.tunnel1_log_options == null ? [] : [var.vpn_connection.tunnel1_log_options]
content {
cloudwatch_log_options {
log_group_arn = tunnel1_log_options.value.cloudwatch_log_group != null ? aws_cloudwatch_log_group.tunnel1[0].arn : tunnel1_log_options.value.cloudwatch_log_options.log_group_arn
log_enabled = tunnel1_log_options.value.cloudwatch_log_options.log_enabled
log_output_format = tunnel1_log_options.value.cloudwatch_log_options.log_output_format
}
}
}

resource "aws_vpn_gateway" "this" {
dynamic "tunnel2_log_options" {
for_each = var.vpn_connection.tunnel2_log_options == null ? [] : [var.vpn_connection.tunnel2_log_options]
content {
cloudwatch_log_options {
log_group_arn = tunnel2_log_options.value.cloudwatch_log_group != null ? aws_cloudwatch_log_group.tunnel2[0].arn : tunnel2_log_options.value.cloudwatch_log_options.log_group_arn
log_enabled = tunnel2_log_options.value.cloudwatch_log_options.log_enabled
log_output_format = tunnel2_log_options.value.cloudwatch_log_options.log_output_format
}
}
}

vpc_id = var.vpc_id
amazon_side_asn = var.amazon_side_asn
tags = merge(
var.tags,
var.vpn_connection.tags,
{
"Name" = local.vgw_name
"Name" = var.vpn_connection.name
},
)
}

resource "aws_customer_gateway" "this" {
count = length(var.cgw_ip_addresses)
bgp_asn = var.vpn_connection.customer_gateway.bgp_asn
certificate_arn = var.vpn_connection.customer_gateway.certificate_arn
device_name = var.vpn_connection.customer_gateway.device_name
ip_address = var.vpn_connection.customer_gateway.ip_address
type = var.vpn_connection.customer_gateway.type

bgp_asn = var.cgw_bgp_asn
ip_address = var.cgw_ip_addresses[count.index]
type = "ipsec.1"
tags = merge(
var.tags,
var.vpn_connection.customer_gateway.tags,
{
"Name" = "${local.cgw_name}_${count.index}"
"Name" = var.vpn_connection.customer_gateway.name
},
)
}

resource "aws_vpn_connection" "this" {
count = length(var.cgw_ip_addresses)
resource "aws_vpn_connection_route" "this" {
for_each = { for route in var.vpn_connection.routes : route.name => route }

vpn_gateway_id = aws_vpn_gateway.this.id
customer_gateway_id = aws_customer_gateway.this[count.index].id
type = "ipsec.1"
static_routes_only = var.static_routes_only
tags = merge(
var.tags,
{
"Name" = "${local.vpn_name}_${count.index}"
},
)
destination_cidr_block = each.value.destination_cidr_block
vpn_connection_id = aws_vpn_connection.this.id
}

resource "aws_vpn_connection_route" "this" {
count = length(var.destination_cidr_blocks)
resource "aws_cloudwatch_log_group" "tunnel1" {
count = var.vpn_connection.tunnel1_log_options != null ? (var.vpn_connection.tunnel1_log_options.cloudwatch_log_group != null ? 1 : 0) : 0

destination_cidr_block = var.destination_cidr_blocks[count.index]
vpn_connection_id = aws_vpn_connection.this[0].id
name = "/aws/vendedlogs/${var.vpn_connection.name}-tunnel1"
log_group_class = var.vpn_connection.tunnel1_log_options.cloudwatch_log_group.log_group_class
skip_destroy = var.vpn_connection.tunnel1_log_options.cloudwatch_log_group.skip_destroy
retention_in_days = var.vpn_connection.tunnel1_log_options.cloudwatch_log_group.retention_in_days
kms_key_id = var.vpn_connection.tunnel1_log_options.cloudwatch_log_group.kms_key_id
tags = merge(
var.vpn_connection.tunnel1_log_options.cloudwatch_log_group.tags,
{
"Name" = "/aws/vendedlogs/${var.vpn_connection.name}-tunnel1"
}
)
}

resource "aws_vpn_gateway_route_propagation" "this" {
count = var.propagating_route_table_count
resource "aws_cloudwatch_log_group" "tunnel2" {
count = var.vpn_connection.tunnel2_log_options != null ? (var.vpn_connection.tunnel2_log_options.cloudwatch_log_group != null ? 1 : 0) : 0

vpn_gateway_id = aws_vpn_gateway.this.id
route_table_id = var.propagating_route_table_ids[count.index]
name = "/aws/vendedlogs/${var.vpn_connection.name}-tunnel2"
log_group_class = var.vpn_connection.tunnel2_log_options.cloudwatch_log_group.log_group_class
skip_destroy = var.vpn_connection.tunnel2_log_options.cloudwatch_log_group.skip_destroy
retention_in_days = var.vpn_connection.tunnel2_log_options.cloudwatch_log_group.retention_in_days
kms_key_id = var.vpn_connection.tunnel2_log_options.cloudwatch_log_group.kms_key_id
tags = merge(
var.vpn_connection.tunnel2_log_options.cloudwatch_log_group.tags,
{
"Name" = "/aws/vendedlogs/${var.vpn_connection.name}-tunnel2"
}
)
}
Loading
Loading