Skip to content

Commit bca5ddc

Browse files
authored
initial commit (#1)
* initial commit
1 parent efa0a37 commit bca5ddc

9 files changed

Lines changed: 436 additions & 0 deletions

File tree

.github/workflows/check.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: format_and_lint
2+
on: [push, pull_request]
3+
4+
jobs:
5+
build:
6+
runs-on: macOS-latest
7+
steps:
8+
- uses: actions/checkout@v1
9+
10+
- name: Install prereq
11+
run: |
12+
brew install docker tfenv tflint
13+
tfenv install
14+
15+
- name: tf fmt
16+
run: |
17+
terraform fmt
18+
- name: tflint
19+
run: |
20+
tflint

.terraform-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.12.23

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 Rhythmic Technologies, Inc.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# terraform-aws-fortigate-vpn
2+
[![GH Action Status](https://github.com/rhythmictech/terraform-aws-fortigate-vpn/workflows/check/badge.svg)](https://github.com/rhythmictech/terraform-aws-fortigate-vpn/actions)
3+
Creates a site-to-site VPN connection intended to terminate to a FortiGate firewall. Creates a template configuration file that can be used to easily configure the connection.
4+
5+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
6+
## Inputs
7+
8+
| Name | Description | Type | Default | Required |
9+
|------|-------------|:----:|:-----:|:-----:|
10+
| account\_name | Name for AWS account side of tunnel | string | n/a | yes |
11+
| customer\_bgp\_asn | BGP for customer side of tunnel | number | n/a | yes |
12+
| customer\_gateway\_type | Type for customer gateway | string | `"ipsec.1"` | no |
13+
| customer\_ip\_address | IP address for customer side | string | n/a | yes |
14+
| customer\_name | Name for customer side of tunnel | string | n/a | yes |
15+
| generate\_fortigate\_config | Generate a FortiGate config template \(does not include PSKs\) | bool | `"true"` | no |
16+
| tags | Tags to add to supported resources | string | n/a | yes |
17+
| transit\_gateway\_id | Transit gateway to attach VPN to \(required if `vpn\_gateway\_id` not set\) | string | `"null"` | no |
18+
| tunnel1\_inside\_cidr | Specify a Tunnel 1 inside CIDR \(optional\) | string | `""` | no |
19+
| tunnel1\_psk | Specify a Tunnel 1 PSK explicitly \(optional\) | string | `""` | no |
20+
| tunnel1\_psk\_version | Version to use for PSK \(increment to generate a new PSK\) | number | `"1"` | no |
21+
| tunnel2\_inside\_cidr | Specify a Tunnel 2 inside CIDR \(optional\) | string | `""` | no |
22+
| tunnel2\_psk | Specify a Tunnel 2 PSK explicitly \(optional\) | string | `""` | no |
23+
| tunnel2\_psk\_version | Version to use for PSK \(increment to generate a new PSK\) | number | `"1"` | no |
24+
| use\_secrets\_manager | Use Secrets Manager to store/manage PSKs | bool | `"true"` | no |
25+
| vgw\_id | Virtual Private Gateway to attach VPN to \(required if `transit\_gateway\_id` not set\) | string | `"null"` | no |
26+
| wan\_interface | WAN interface to use in fortigate config template | string | `"wan1"` | no |
27+
28+
## Outputs
29+
30+
| Name | Description |
31+
|------|-------------|
32+
| customer\_gateway\_bgp\_asn | Customer Gateway BGP ASN |
33+
| customer\_gateway\_id | Customer Gateway ID |
34+
| customer\_gateway\_ip\_address | Customer Gateway IP Address |
35+
| vpn\_connection\_tunnel1\_address | Tunnel 1 Public IP Address |
36+
| vpn\_connection\_tunnel1\_bgp\_asn | Tunnel 1 BGP ASN |
37+
| vpn\_connection\_tunnel1\_cgw\_inside\_address | Tunnel 1 Customer Inside IP Address |
38+
| vpn\_connection\_tunnel1\_preshared\_key | Tunnel 1 Preshared Key |
39+
| vpn\_connection\_tunnel1\_vgw\_inside\_address | Tunnel 1 AWS Inside IP Address |
40+
| vpn\_connection\_tunnel2\_address | Tunnel 2 Public IP Address |
41+
| vpn\_connection\_tunnel2\_bgp\_asn | Tunnel 2 BGP ASN |
42+
| vpn\_connection\_tunnel2\_cgw\_inside\_address | Tunnel 2 Customer Inside IP Address |
43+
| vpn\_connection\_tunnel2\_preshared\_key | Tunnel 2 Preshared Key |
44+
| vpn\_connection\_tunnel2\_vgw\_inside\_address | Tunnel 2 AWS Inside IP Address |
45+
| vpn\_connection\_vpn\_gw\_id | VPN Gateway ID |
46+
47+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

fortigate_config.txt.tpl

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
config vpn ipsec phase1-interface
2+
edit "${shortname}1"
3+
set interface "${wan_interface}"
4+
set dpd enable
5+
set local-gw ${customer_ip_address}
6+
set dhgrp 2
7+
set proposal aes128-sha1
8+
set keylife 28800
9+
set remote-gw ${tunnel1_address}
10+
set psksecret PSK1
11+
set dpd-retryinterval 10
12+
set comments "${account_name}<->${customer_name}1"
13+
next
14+
end
15+
16+
config vpn ipsec phase2-interface
17+
edit "${shortname}1"
18+
set phase1name "${shortname}1"
19+
set proposal aes128-sha1
20+
set dhgrp 2
21+
set pfs enable
22+
set keylifeseconds 3600
23+
next
24+
end
25+
26+
config system interface
27+
edit "${shortname}1"
28+
set vdom "root"
29+
set ip ${tunnel1_inside_address_customer} 255.255.255.255
30+
set allowaccess ping
31+
set type tunnel
32+
set tcp-mss 1379
33+
set remote-ip ${tunnel1_inside_address_amazon} 255.255.255.255
34+
set comments "${account_name}<->${customer_name}1"
35+
set interface "${wan_interface}"
36+
next
37+
end
38+
39+
config router bgp
40+
config neighbor
41+
edit ${tunnel1_inside_address_amazon}
42+
set capability-graceful-restart enable
43+
set soft-reconfiguration enable
44+
set remote-as ${amazon_bgp_asn}
45+
next
46+
end
47+
end
48+
49+
config vpn ipsec phase1-interface
50+
edit "${shortname}2"
51+
set interface "${wan_interface}"
52+
set dpd enable
53+
set local-gw ${customer_ip_address}
54+
set dhgrp 2
55+
set proposal aes128-sha1
56+
set keylife 28800
57+
set remote-gw ${tunnel2_address}
58+
set psksecret PSK2
59+
set dpd-retryinterval 10
60+
set comments "${account_name}<->${customer_name}2"
61+
next
62+
end
63+
64+
config vpn ipsec phase2-interface
65+
edit "${shortname}2"
66+
set phase1name "${shortname}2"
67+
set proposal aes128-sha1
68+
set dhgrp 2
69+
set pfs enable
70+
set keylifeseconds 3600
71+
next
72+
end
73+
74+
config system interface
75+
edit "${shortname}2"
76+
set vdom "root"
77+
set ip ${tunnel2_inside_address_customer} 255.255.255.255
78+
set allowaccess ping
79+
set type tunnel
80+
set tcp-mss 1379
81+
set remote-ip ${tunnel2_inside_address_amazon} 255.255.255.255
82+
set interface "${wan_interface}"
83+
set description "${account_name}<->${customer_name}2"
84+
next
85+
end
86+
87+
config router bgp
88+
config neighbor
89+
edit ${tunnel2_inside_address_amazon}
90+
set capability-graceful-restart enable
91+
set soft-reconfiguration enable
92+
set remote-as ${amazon_bgp_asn}
93+
next
94+
end
95+
end

main.tf

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
data "aws_vpn_gateway" "this" {
2+
id = var.vgw_id
3+
}
4+
5+
data "aws_ec2_transit_gateway" "this" {
6+
id = var.transit_gateway_id
7+
}
8+
9+
module "psk1" {
10+
source = "git::https://github.com/rhythmictech/terraform-aws-secretsmanager-random-secret?ref=v1.1.1"
11+
name = "${var.account_name}/${var.customer_name}-psk1-secret"
12+
create_secret = var.use_secrets_manager
13+
length = 40
14+
min_special = 3
15+
override_special = "._"
16+
pass_version = var.tunnel1_psk_version
17+
use_special = true
18+
tags = var.tags
19+
}
20+
21+
module "psk2" {
22+
source = "git::https://github.com/rhythmictech/terraform-aws-secretsmanager-random-secret?ref=v1.1.1"
23+
name = "${var.account_name}/${var.customer_name}-psk2-secret"
24+
create_secret = var.use_secrets_manager
25+
length = 40
26+
min_special = 3
27+
override_special = "._"
28+
pass_version = var.tunnel2_psk_version
29+
tags = var.tags
30+
use_special = true
31+
}
32+
33+
locals {
34+
35+
tags_with_name = merge(var.tags, {
36+
"Name" = "${var.account_name}<=>${var.customer_name}"
37+
}
38+
)
39+
tunnel1_psk = var.use_secrets_manager ? module.psk1.secret : var.tunnel1_psk
40+
tunnel2_psk = var.use_secrets_manager ? module.psk2.secret : var.tunnel2_psk
41+
42+
# compute aws bgp asn
43+
amazon_bgp_asn = var.vgw_id == null ? data.aws_ec2_transit_gateway.this.amazon_side_asn : data.aws_vpn_gateway.this.amazon_side_asn
44+
}
45+
46+
resource "aws_customer_gateway" "this" {
47+
bgp_asn = var.customer_bgp_asn
48+
ip_address = var.customer_ip_address
49+
tags = local.tags_with_name
50+
type = var.customer_gateway_type
51+
}
52+
53+
resource "aws_vpn_connection" "this" {
54+
customer_gateway_id = aws_customer_gateway.this.id
55+
tags = local.tags_with_name
56+
transit_gateway_id = var.transit_gateway_id
57+
tunnel1_inside_cidr = var.tunnel1_inside_cidr
58+
tunnel1_preshared_key = local.tunnel1_psk
59+
tunnel2_inside_cidr = var.tunnel2_inside_cidr
60+
tunnel2_preshared_key = local.tunnel2_psk
61+
type = aws_customer_gateway.this.type
62+
vpn_gateway_id = var.vgw_id
63+
}
64+
65+
resource "local_file" "this" {
66+
count = var.generate_fortigate_config ? 1 : 0
67+
content = templatefile("${path.module}/fortigate_config.txt.tpl",
68+
{
69+
account_name = var.account_name
70+
amazon_bgp_asn = local.amazon_bgp_asn
71+
customer_bgp_asn = var.customer_bgp_asn
72+
customer_ip_address = var.customer_ip_address
73+
customer_name = var.customer_name
74+
shortname = substr(var.account_name, 0, 14)
75+
tunnel1_address = aws_vpn_connection.this.tunnel1_address
76+
tunnel1_inside_address_amazon = aws_vpn_connection.this.tunnel1_vgw_inside_address
77+
tunnel1_inside_address_customer = aws_vpn_connection.this.tunnel1_cgw_inside_address
78+
tunnel2_address = aws_vpn_connection.this.tunnel2_address
79+
tunnel2_inside_address_amazon = aws_vpn_connection.this.tunnel2_vgw_inside_address
80+
tunnel2_inside_address_customer = aws_vpn_connection.this.tunnel2_cgw_inside_address
81+
wan_interface = var.wan_interface
82+
}
83+
)
84+
filename = "${var.account_name}-${var.customer_name}-fortigate_config.txt"
85+
}

outputs.tf

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
output "customer_gateway_bgp_asn" {
2+
description = "Customer Gateway BGP ASN"
3+
value = aws_customer_gateway.this.bgp_asn
4+
}
5+
6+
output "customer_gateway_id" {
7+
description = "Customer Gateway ID"
8+
value = aws_customer_gateway.this.id
9+
}
10+
11+
output "customer_gateway_ip_address" {
12+
description = "Customer Gateway IP Address"
13+
value = aws_customer_gateway.this.ip_address
14+
}
15+
16+
output "vpn_connection_tunnel1_address" {
17+
description = "Tunnel 1 Public IP Address"
18+
value = aws_vpn_connection.this.tunnel1_address
19+
}
20+
21+
output "vpn_connection_tunnel1_bgp_asn" {
22+
description = "Tunnel 1 BGP ASN"
23+
value = aws_vpn_connection.this.tunnel1_bgp_asn
24+
}
25+
output "vpn_connection_tunnel1_cgw_inside_address" {
26+
description = "Tunnel 1 Customer Inside IP Address"
27+
value = aws_vpn_connection.this.tunnel1_cgw_inside_address
28+
}
29+
30+
output "vpn_connection_tunnel1_preshared_key" {
31+
description = "Tunnel 1 Preshared Key"
32+
value = aws_vpn_connection.this.tunnel1_preshared_key
33+
}
34+
35+
output "vpn_connection_tunnel1_vgw_inside_address" {
36+
description = "Tunnel 1 AWS Inside IP Address"
37+
value = aws_vpn_connection.this.tunnel1_vgw_inside_address
38+
}
39+
40+
output "vpn_connection_tunnel2_address" {
41+
description = "Tunnel 2 Public IP Address"
42+
value = aws_vpn_connection.this.tunnel2_address
43+
}
44+
45+
output "vpn_connection_tunnel2_bgp_asn" {
46+
description = "Tunnel 2 BGP ASN"
47+
value = aws_vpn_connection.this.tunnel2_bgp_asn
48+
}
49+
50+
output "vpn_connection_tunnel2_cgw_inside_address" {
51+
description = "Tunnel 2 Customer Inside IP Address"
52+
value = aws_vpn_connection.this.tunnel2_cgw_inside_address
53+
}
54+
55+
output "vpn_connection_tunnel2_preshared_key" {
56+
description = "Tunnel 2 Preshared Key"
57+
value = aws_vpn_connection.this.tunnel2_preshared_key
58+
}
59+
60+
output "vpn_connection_tunnel2_vgw_inside_address" {
61+
description = "Tunnel 2 AWS Inside IP Address"
62+
value = aws_vpn_connection.this.tunnel2_vgw_inside_address
63+
}
64+
65+
output "vpn_connection_vpn_gw_id" {
66+
description = "VPN Gateway ID"
67+
value = aws_vpn_connection.this.id
68+
}

0 commit comments

Comments
 (0)