-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from hazelops/feature/initial
Terraform AWS Wireguard module
- Loading branch information
Showing
13 changed files
with
1,205 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Local .terraform directories | ||
**/.terraform/* | ||
|
||
# Terraform lockfile | ||
.terraform.lock.hcl | ||
|
||
# .tfstate files | ||
*.tfstate | ||
*.tfstate.* | ||
|
||
# Crash log files | ||
crash.log | ||
|
||
# Exclude all .tfvars files, which are likely to contain sentitive data, such as | ||
# password, private keys, and other secrets. These should not be part of version | ||
# control as they are data points which are potentially sensitive and subject | ||
# to change depending on the environment. | ||
*.tfvars | ||
|
||
# Ignore override files as they are usually used to override resources locally and so | ||
# are not checked in | ||
override.tf | ||
override.tf.json | ||
*_override.tf | ||
*_override.tf.json | ||
|
||
# Ignore CLI configuration files | ||
.terraformrc | ||
terraform.rc |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,88 @@ | ||
# terraform-aws-wireguard | ||
# Terraform AWS WireGuard | ||
|
||
A Terraform module to deploy a WireGuard VPN server on AWS. | ||
|
||
### Prerequisites | ||
Before using this module, you'll need to: | ||
|
||
1. Install the [WireGuard tools](https://www.wireguard.com/install/) for your OS. | ||
|
||
2. Generate a key pair for each client: | ||
```bash | ||
wg genkey | tee client1-privatekey | wg pubkey > client1-publickey | ||
``` | ||
|
||
3. Generate a key pair for the server | ||
```bash | ||
wg genkey | tee server-privatekey | wg pubkey > server-publickey | ||
``` | ||
4. Add each client's public key, along with the next available IP address to the `wg_clients` list. | ||
|
||
5. Add server's private key to the `wg_server_private_key` variable. You can use AWS SSM Parameter store to store and read server private key. | ||
|
||
|
||
<!-- BEGINNING OF GENERATED BY TERRAFORM-DOCS --> | ||
|
||
## Requirements | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.5 | | ||
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 3.0 | | ||
|
||
## Providers | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="provider_aws"></a> [aws](#provider\_aws) | ~> 3.0 | | ||
| <a name="provider_template"></a> [template](#provider\_template) | n/a | | ||
|
||
## Modules | ||
|
||
No modules. | ||
|
||
## Resources | ||
|
||
| Name | Type | | ||
|------|------| | ||
| [aws_autoscaling_group.wireguard_asg](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/autoscaling_group) | resource | | ||
| [aws_eip.wireguard](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource | | ||
| [aws_iam_instance_profile.wireguard_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | | ||
| [aws_iam_policy.wireguard_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | ||
| [aws_iam_role.wireguard_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | ||
| [aws_iam_role_policy_attachment.wireguard_roleattach](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | ||
| [aws_launch_configuration.wireguard_launch_config](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_configuration) | resource | | ||
| [aws_route53_record.wireguard](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | | ||
| [aws_security_group.sg_wireguard](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | | ||
| [aws_ami.ubuntu](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | | ||
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | ||
| [aws_iam_policy_document.ec2_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | ||
| [aws_iam_policy_document.wireguard_policy_doc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | ||
| [template_file.wg_client_data_json](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file) | data source | | ||
|
||
## Inputs | ||
|
||
| Name | Description | Type | Default | Required | | ||
|------|-------------|------|---------|:--------:| | ||
| <a name="input_env"></a> [env](#input\_env) | The name of environment for WireGuard. Used to differentiate multiple deployments. | `any` | n/a | yes | | ||
| <a name="input_instance_type"></a> [instance\_type](#input\_instance\_type) | The machine type to launch, some machines may offer higher throughput for higher use cases. | `string` | `"t3.nano"` | no | | ||
| <a name="input_region"></a> [region](#input\_region) | n/a | `string` | n/a | yes | | ||
| <a name="input_route53_hosted_zone_id"></a> [route53\_hosted\_zone\_id](#input\_route53\_hosted\_zone\_id) | Route53 Hosted zone ID. | `string` | `null` | no | | ||
| <a name="input_route53_record_name"></a> [route53\_record\_name](#input\_route53\_record\_name) | Route53 Record name. | `string` | `null` | no | | ||
| <a name="input_ssh_key_id"></a> [ssh\_key\_id](#input\_ssh\_key\_id) | A SSH public key ID to add to the VPN instance. | `any` | n/a | yes | | ||
| <a name="input_subnet_ids"></a> [subnet\_ids](#input\_subnet\_ids) | A list of subnets for the Autoscaling Group to use for launching instances. May be a single subnet, but it must be an element in a list. | `list(string)` | n/a | yes | | ||
| <a name="input_target_group_arns"></a> [target\_group\_arns](#input\_target\_group\_arns) | Running a scaling group behind an LB requires this variable, default null means it won't be included if not set. | `list(string)` | `null` | no | | ||
| <a name="input_use_eip"></a> [use\_eip](#input\_use\_eip) | Whether to enable Elastic IP switching code in user-data on wg server startup. If true, eip\_id must also be set to the ID of the Elastic IP. | `bool` | `false` | no | | ||
| <a name="input_use_route53"></a> [use\_route53](#input\_use\_route53) | Whether to use Route53 | `bool` | `false` | no | | ||
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | The VPC ID in which Terraform will launch the resources. | `any` | n/a | yes | | ||
| <a name="input_wg_clients"></a> [wg\_clients](#input\_wg\_clients) | List of client objects with IP and public key. See Usage in README for details. | `list(object({ client_friendly_name = string, client_public_key = string, client_allowed_cidr = string }))` | n/a | yes | | ||
| <a name="input_wg_persistent_keepalive"></a> [wg\_persistent\_keepalive](#input\_wg\_persistent\_keepalive) | Persistent Keepalive - useful for helping connection stability over NATs. | `number` | `25` | no | | ||
| <a name="input_wg_server_interface"></a> [wg\_server\_interface](#input\_wg\_server\_interface) | The default interface to forward network traffic to. | `string` | `"eth0"` | no | | ||
| <a name="input_wg_server_net"></a> [wg\_server\_net](#input\_wg\_server\_net) | IP range for vpn server - make sure your Client ips are in this range but not the specific ip i.e. not .1 | `string` | `"10.0.0.1/24"` | no | | ||
| <a name="input_wg_server_port"></a> [wg\_server\_port](#input\_wg\_server\_port) | Port for the vpn server. | `number` | `51820` | no | | ||
| <a name="input_wg_server_private_key"></a> [wg\_server\_private\_key](#input\_wg\_server\_private\_key) | WG server private key. | `string` | n/a | yes | | ||
|
||
## Outputs | ||
|
||
No outputs. | ||
<!-- END OF GENERATED BY TERRAFORM-DOCS --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
module "wireguard" { | ||
source = "hazelops/wireguard/aws" | ||
version = "~>1.0" | ||
env = your-env | ||
region = your-aws-region | ||
use_eip = true | ||
ssh_key_id = "your-ec2-key-id" | ||
instance_type = "t3.nano" | ||
wg_server_net = "10.0.0.1/24" | ||
wg_server_port = 51820 | ||
wg_persistent_keepalive = 25 | ||
wg_server_interface = "eth0" | ||
use_route53 = false | ||
subnet_ids = ["your-vpc-subnets"] | ||
vpc_id = "id-of-your-vpc" | ||
wg_server_private_key = data.aws_ssm_parameter.wireguard_server_private_key.value | ||
wg_clients = [ | ||
{ client_friendly_name = "user1" | ||
client_allowed_cidr = "10.0.0.3/24" | ||
client_public_key = "user1-public-key" }, | ||
{ client_friendly_name = "user2" | ||
client_allowed_cidr = "10.0.0.4/24" | ||
client_public_key = "user2-public-key" } | ||
] | ||
} | ||
|
||
data "aws_ssm_parameter" "wireguard_server_private_key" { | ||
name = "/mgmt/wg-server-private-key" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
module "wireguard" { | ||
source = "hazelops/wireguard/aws" | ||
version = "~>1.0" | ||
env = your-env | ||
region = your-aws-region | ||
use_eip = true | ||
ssh_key_id = "your-ec2-key-id" | ||
subnet_ids = ["vpc-subnets"] | ||
vpc_id = "id-of-your-vpc" | ||
wg_server_private_key = data.aws_ssm_parameter.wireguard_server_private_key.value | ||
wg_clients = [ | ||
{ client_friendly_name = "user1" | ||
client_allowed_cidr = "10.0.0.3/24" | ||
client_public_key = "user1-public-key" }, | ||
{ client_friendly_name = "user2" | ||
client_allowed_cidr = "10.0.0.4/24" | ||
client_public_key = "user2-public-key" } | ||
] | ||
} | ||
|
||
data "aws_ssm_parameter" "wireguard_server_private_key" { | ||
name = "/mgmt/wg-server-private-key" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
data "aws_iam_policy_document" "ec2_assume_role" { | ||
statement { | ||
actions = [ | ||
"sts:AssumeRole" | ||
] | ||
|
||
principals { | ||
type = "Service" | ||
identifiers = ["ec2.amazonaws.com"] | ||
} | ||
} | ||
} | ||
|
||
data "aws_iam_policy_document" "wireguard_policy_doc" { | ||
statement { | ||
actions = [ | ||
"ec2:AssociateAddress", | ||
"ssm:GetParameter" | ||
] | ||
|
||
resources = ["*"] | ||
} | ||
} | ||
|
||
data "aws_caller_identity" "current" {} | ||
|
||
resource "aws_iam_policy" "wireguard_policy" { | ||
name = "${var.env}-${var.region}-tf-wireguard" | ||
description = "Terraform Managed. Allows Wireguard instance to attach EIP." | ||
policy = data.aws_iam_policy_document.wireguard_policy_doc.json | ||
count = (var.use_eip ? 1 : 0) # only used for EIP mode | ||
} | ||
|
||
resource "aws_iam_role" "wireguard_role" { | ||
name = "${var.env}-${var.region}-tf-wireguard" | ||
description = "Terraform Managed. Role to allow Wireguard instance to attach EIP." | ||
path = "/" | ||
assume_role_policy = data.aws_iam_policy_document.ec2_assume_role.json | ||
count = (var.use_eip ? 1 : 0) # only used for EIP mode | ||
} | ||
|
||
resource "aws_iam_role_policy_attachment" "wireguard_roleattach" { | ||
role = aws_iam_role.wireguard_role[0].name | ||
policy_arn = aws_iam_policy.wireguard_policy[0].arn | ||
count = (var.use_eip ? 1 : 0) # only used for EIP mode | ||
} | ||
|
||
resource "aws_iam_instance_profile" "wireguard_profile" { | ||
name = "${var.env}-${var.region}-tf-wireguard" | ||
role = aws_iam_role.wireguard_role[0].name | ||
count = (var.use_eip ? 1 : 0) # only used for EIP mode | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
resource "aws_eip" "wireguard" { | ||
vpc = true | ||
tags = { | ||
Name = "${var.env}-wireguard" | ||
} | ||
} | ||
|
||
resource "aws_route53_record" "wireguard" { | ||
count = var.use_route53 ? 1 : 0 | ||
allow_overwrite = true | ||
set_identifier = "${var.env}-${var.region}-wireguard" | ||
zone_id = var.route53_hosted_zone_id | ||
name = var.route53_record_name | ||
type = "A" | ||
ttl = "60" | ||
records = [aws_eip.wireguard.public_ip] | ||
} | ||
|
||
data "template_file" "wg_client_data_json" { | ||
template = file("${path.module}/templates/client-data.tpl") | ||
count = length(var.wg_clients) | ||
|
||
vars = { | ||
client_friendly_name = var.wg_clients[count.index].client_friendly_name | ||
client_public_key = var.wg_clients[count.index].client_public_key | ||
client_allowed_cidr = var.wg_clients[count.index].client_allowed_cidr | ||
persistent_keepalive = var.wg_persistent_keepalive | ||
} | ||
} | ||
|
||
data "aws_ami" "ubuntu" { | ||
most_recent = true | ||
filter { | ||
name = "name" | ||
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] | ||
} | ||
filter { | ||
name = "virtualization-type" | ||
values = ["hvm"] | ||
} | ||
owners = ["099720109477"] # Canonical | ||
} | ||
|
||
resource "aws_launch_configuration" "wireguard_launch_config" { | ||
name_prefix = "${var.env}-wireguard-" | ||
image_id = data.aws_ami.ubuntu.id | ||
instance_type = var.instance_type | ||
key_name = var.ssh_key_id | ||
iam_instance_profile = (var.use_eip ? aws_iam_instance_profile.wireguard_profile[0].name : null) | ||
user_data = templatefile("${path.module}/templates/user-data.txt", { | ||
wg_server_private_key = var.wg_server_private_key, | ||
wg_server_net = var.wg_server_net, | ||
wg_server_port = var.wg_server_port, | ||
peers = join("\n", data.template_file.wg_client_data_json.*.rendered), | ||
use_eip = var.use_eip ? "enabled" : "disabled", | ||
eip_id = aws_eip.wireguard.id, | ||
wg_server_interface = var.wg_server_interface | ||
}) | ||
security_groups = [aws_security_group.sg_wireguard.id] | ||
associate_public_ip_address = var.use_eip | ||
|
||
lifecycle { | ||
create_before_destroy = true | ||
} | ||
} | ||
|
||
resource "aws_autoscaling_group" "wireguard_asg" { | ||
name = aws_launch_configuration.wireguard_launch_config.name | ||
launch_configuration = aws_launch_configuration.wireguard_launch_config.name | ||
min_size = 1 | ||
desired_capacity = 1 | ||
max_size = 1 | ||
vpc_zone_identifier = var.subnet_ids | ||
health_check_type = "EC2" | ||
termination_policies = ["OldestLaunchConfiguration", "OldestInstance"] | ||
target_group_arns = var.target_group_arns | ||
|
||
lifecycle { | ||
create_before_destroy = true | ||
} | ||
|
||
tags = [ | ||
{ | ||
key = "Name" | ||
value = aws_launch_configuration.wireguard_launch_config.name | ||
propagate_at_launch = true | ||
}, | ||
{ | ||
key = "Project" | ||
value = "wireguard" | ||
propagate_at_launch = true | ||
}, | ||
{ | ||
key = "env" | ||
value = var.env | ||
propagate_at_launch = true | ||
}, | ||
{ | ||
key = "tf-managed" | ||
value = "True" | ||
propagate_at_launch = true | ||
}, | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
resource "aws_security_group" "sg_wireguard" { | ||
name = "${var.env}-${var.region}-wireguard" | ||
description = "Terraform Managed. Allow Wireguard client traffic from internet." | ||
vpc_id = var.vpc_id | ||
|
||
tags = { | ||
Name = "${var.env}-${var.region}-wireguard" | ||
Project = "wireguard" | ||
tf-managed = "True" | ||
env = var.env | ||
} | ||
|
||
ingress { | ||
from_port = var.wg_server_port | ||
to_port = var.wg_server_port | ||
protocol = "udp" | ||
cidr_blocks = ["0.0.0.0/0"] | ||
} | ||
|
||
ingress { | ||
from_port = 22 | ||
to_port = 22 | ||
protocol = "tcp" | ||
cidr_blocks = ["0.0.0.0/0"] | ||
} | ||
|
||
egress { | ||
from_port = 0 | ||
to_port = 0 | ||
protocol = "-1" | ||
cidr_blocks = ["0.0.0.0/0"] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
[Peer] | ||
# client_friendly_name = ${client_friendly_name} | ||
PublicKey = ${client_public_key} | ||
AllowedIPs = ${client_allowed_cidr} | ||
PersistentKeepalive = ${persistent_keepalive} |
Oops, something went wrong.