Skip to content

Commit cf3bb11

Browse files
committed
port version 0.0.2 from legos
1 parent 7987a99 commit cf3bb11

File tree

7 files changed

+338
-0
lines changed

7 files changed

+338
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.tfstate*
2+
.terraform/

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# CHANGELOG
2+
3+
### ???
4+
5+
- Feature: Automatically push instance's subnet route into `server.conf`
6+
7+
### 0.0.2
8+
9+
- Fix: use updated `awscli` client from pip instead of apt
10+
11+
### 0.0.1
12+
13+
- Basic functioning openvpn server working off us-east-1
14+

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Terraform AWS OpenVPN Module

certs/main.tf

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
# openvpn_server
2+
3+
provider "aws" {
4+
region = "${var.region}"
5+
}
6+
7+
/* ---------------------------- */
8+
/* IAM Role & Instance Profile */
9+
/* ---------------------------- */
10+
11+
resource "aws_iam_role" "vpn_role" {
12+
name = "${var.region}-${var.stack_item_label}-vpn"
13+
path = "/"
14+
15+
assume_role_policy = <<EOF
16+
{
17+
"Version": "2012-10-17",
18+
"Statement": [
19+
{
20+
"Effect": "Allow",
21+
"Action": "sts:AssumeRole",
22+
"Principal": {
23+
"Service": "ec2.amazonaws.com"
24+
}
25+
}
26+
]
27+
}
28+
EOF
29+
}
30+
31+
resource "aws_iam_role_policy" "s3_vpn" {
32+
name = "s3_vpn"
33+
role = "${aws_iam_role.vpn_role.id}"
34+
35+
policy = <<EOF
36+
{
37+
"Version": "2012-10-17",
38+
"Statement": [
39+
{
40+
"Effect": "Allow",
41+
"Action": [
42+
"s3:Get*"
43+
],
44+
"Resource": [
45+
"arn:aws:s3:::${var.s3_path}",
46+
"arn:aws:s3:::${var.s3_path}/*"
47+
]
48+
},
49+
{
50+
"Effect": "Allow",
51+
"Action": [
52+
"s3:List*"
53+
],
54+
"Resource": [
55+
"arn:aws:s3:::${var.s3_bucket}"
56+
]
57+
}
58+
]
59+
}
60+
EOF
61+
}
62+
63+
resource "aws_iam_role_policy" "tags" {
64+
name = "tags"
65+
role = "${aws_iam_role.vpn_role.id}"
66+
67+
policy = <<EOF
68+
{
69+
"Version": "2012-10-17",
70+
"Statement": [
71+
{
72+
"Effect": "Allow",
73+
"Action": [
74+
"ec2:CreateTags",
75+
"ec2:AssociateAddress",
76+
"ec2:DescribeAddresses",
77+
"ec2:DescribeInstances"
78+
],
79+
"Resource": "*"
80+
}
81+
]
82+
}
83+
EOF
84+
}
85+
86+
resource "aws_iam_instance_profile" "vpn_profile" {
87+
name = "${var.region}-${var.stack_item_label}-vpn"
88+
roles = ["${aws_iam_role.vpn_role.name}"]
89+
}
90+
91+
/* ---------------------------- */
92+
/* Security Group */
93+
/* ---------------------------- */
94+
resource "aws_security_group_rule" "allow_all_out" {
95+
type = "egress"
96+
from_port = 0
97+
to_port = 0
98+
protocol = "-1"
99+
cidr_blocks = ["0.0.0.0/0"]
100+
101+
security_group_id = "${module.asg.sg_id}"
102+
}
103+
104+
resource "aws_security_group_rule" "allow_ssh_in_tcp" {
105+
type = "ingress"
106+
from_port = 22
107+
to_port = 22
108+
protocol = "tcp"
109+
cidr_blocks = ["${split(",",var.cidr_whitelist)}"]
110+
111+
security_group_id = "${module.asg.sg_id}"
112+
}
113+
114+
resource "aws_security_group_rule" "allow_openvpn_in_tdp" {
115+
type = "ingress"
116+
from_port = 1194
117+
to_port = 1194
118+
protocol = "tcp"
119+
cidr_blocks = ["${split(",",var.cidr_whitelist)}"]
120+
121+
security_group_id = "${module.asg.sg_id}"
122+
}
123+
124+
resource "aws_security_group_rule" "allow_ping_request_icmp" {
125+
type = "ingress"
126+
from_port = 8
127+
to_port = 0
128+
protocol = "icmp"
129+
cidr_blocks = ["0.0.0.0/0"]
130+
131+
security_group_id = "${module.asg.sg_id}"
132+
}
133+
134+
resource "aws_security_group_rule" "allow_ping_reply_icmp" {
135+
type = "ingress"
136+
from_port = 0
137+
to_port = 0
138+
protocol = "icmp"
139+
cidr_blocks = ["0.0.0.0/0"]
140+
141+
security_group_id = "${module.asg.sg_id}"
142+
}
143+
144+
/* ---------------------------- */
145+
/* User Data */
146+
/* ---------------------------- */
147+
resource "template_file" "user_data" {
148+
template = "${file("${path.module}/templates/user_data.tpl")}"
149+
150+
vars {
151+
instance_number = "${count.index}"
152+
hostname = "${var.role}-${count.index}"
153+
region = "${var.region}"
154+
stack_item_label = "${var.stack_item_label}"
155+
role = "${var.role}"
156+
s3_path = "${var.s3_path}"
157+
route_cidrs = "${var.route_cidrs}"
158+
}
159+
160+
lifecycle {
161+
create_before_destroy = true
162+
}
163+
}
164+
165+
module "asg" {
166+
source = "github.com/unifio/terraform-aws-asg?ref=v0.2.0//group"
167+
168+
# Resource tags
169+
stack_item_label = "${var.stack_item_label}-vpn-asg"
170+
stack_item_fullname = "${var.stack_item_fullname}-vpn"
171+
172+
# VPC parameters
173+
vpc_id = "${var.vpc_id}"
174+
subnets = "${var.subnets}"
175+
region = "${var.region}"
176+
177+
# LC parameters
178+
ami = "${var.ami}"
179+
instance_type = "${var.instance_type}"
180+
instance_profile = "${aws_iam_instance_profile.vpn_profile.id}"
181+
user_data = "${template_file.user_data.rendered}"
182+
key_name = "${var.key_name}"
183+
ebs_optimized = false
184+
185+
# ASG parameters
186+
max_size = 2
187+
min_size = 1
188+
hc_grace_period = 300
189+
hc_check_type = "EC2"
190+
min_elb_capacity = 1
191+
load_balancers = "${aws_elb.elb.id}"
192+
}
193+
194+
# Create a new load balancer
195+
resource "aws_elb" "elb" {
196+
name = "${var.stack_item_label}-vpn-elb"
197+
subnets = ["${split(",",var.subnets)}"]
198+
internal = false
199+
security_groups = ["${module.asg.sg_id}"]
200+
201+
listener {
202+
instance_port = 1194
203+
instance_protocol = "tcp"
204+
lb_port = 1194
205+
lb_protocol = "tcp"
206+
}
207+
208+
health_check {
209+
healthy_threshold = 2
210+
unhealthy_threshold = 2
211+
timeout = 3
212+
target = "TCP:1194"
213+
interval = 30
214+
}
215+
216+
tags {
217+
Name = "${var.stack_item_label}-vpn-elb"
218+
application = "${var.stack_item_fullname}-vpn"
219+
managed_by = "terraform"
220+
}
221+
}
222+
223+
# Create a Route53 record
224+

certs/outputs.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# openvpn_server - Output Variables
2+
3+
/* ---------------------------- */
4+
## VPN server security group ID */
5+
/* ---------------------------- */
6+
output "vpn_server_sg_id" {
7+
value = "${module.asg.sg_id}"
8+
}
9+
10+
output "cidr_whitelist" {
11+
value = "${var.cidr_whitelist}"
12+
}

certs/templates/user_data.tpl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#cloud-config
2+
environment:
3+
stack_item_label: ${stack_item_label}
4+
hostname: ${hostname}
5+
aws_region: ${region}
6+
instance_role: ${role}
7+
instance_number: ${instance_number}
8+
runcmd:
9+
- echo "OPENVPN_CERT_SOURCE=s3://${s3_path}" > /etc/openvpn/get-openvpn-certs.env
10+
- echo "push \"route $(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g') 255.255.255.255 net_gateway\"" >> /etc/openvpn/server.conf
11+
- echo "push \"route ${cidrhost(element(split(",",route_cidrs),1), 0)} ${cidrnetmask(element(split(",",route_cidrs),1))}\"" >> /etc/openvpn/server.conf
12+
- echo "push \"route ${cidrhost(element(split(",",route_cidrs),2), 0)} ${cidrnetmask(element(split(",",route_cidrs),2))}\"" >> /etc/openvpn/server.conf
13+
- echo "push \"route ${cidrhost(element(split(",",route_cidrs),3), 0)} ${cidrnetmask(element(split(",",route_cidrs),3))}\"" >> /etc/openvpn/server.conf
14+
- echo "push \"route ${cidrhost(element(split(",",route_cidrs),4), 0)} ${cidrnetmask(element(split(",",route_cidrs),4))}\"" >> /etc/openvpn/server.conf
15+
- systemctl start get-openvpn-certs
16+
- systemctl restart openvpn@server
17+
- systemctl restart iptables
18+
19+
output : { all : '| tee -a /var/log/cloud-init-output.log' }

certs/variables.tf

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# openvpn_server - Variables
2+
3+
variable "ami" {
4+
description = "Artifact AMI"
5+
}
6+
7+
variable "stack_item_fullname" {}
8+
9+
variable "stack_item_label" {}
10+
11+
#
12+
# 0 - if instance is a standalone instance outside a VPC
13+
# 1 - if instance is in a vpc
14+
#
15+
variable "in_vpc" {
16+
default = 0
17+
}
18+
19+
variable "vpc_id" {
20+
default = ""
21+
}
22+
23+
variable "security_groups" {
24+
default = ""
25+
}
26+
27+
# Which subnet the vpn servers will run in.
28+
variable "subnets" {
29+
default = ""
30+
}
31+
32+
# TODO: expects 4 subnets to map as internal network routes.
33+
# Fix the magic # problem
34+
variable "route_cidrs" {
35+
default = ""
36+
}
37+
38+
variable "key_name" {}
39+
40+
#
41+
# m3.medium - if instance is a standalone instance outside a VPC
42+
# t2.small - if instance is in a vpc
43+
#
44+
variable "instance_type" {}
45+
46+
variable "region" {}
47+
48+
variable "release" {
49+
default = "0.0.2"
50+
}
51+
52+
variable "role" {
53+
default = "vpn_server"
54+
}
55+
56+
# Do not include the trailing slash
57+
variable "s3_path" {}
58+
59+
variable "s3_bucket" {}
60+
61+
variable "sns_topic_arn" {}
62+
63+
# From AWS limits, max rules for an SG is ~50
64+
variable "cidr_whitelist" {
65+
default = "0.0.0.0/0"
66+
}

0 commit comments

Comments
 (0)