Skip to content

Commit

Permalink
Version 1.4.0
Browse files Browse the repository at this point in the history
Separate NAT instance configuration using a 'terraform module'.
  • Loading branch information
vulturm authored and Mihai Vultur committed Oct 13, 2017
1 parent 9dc7f69 commit b8862fa
Show file tree
Hide file tree
Showing 16 changed files with 335 additions and 71 deletions.
3 changes: 3 additions & 0 deletions DevOpsVPC/.gitignore → .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ terraform.tfstate
*.bak
*~
.*.swp
# statefiles/ -- is difficult to store them in SCM,
# better configure terraform remote state storage
statefiles/
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ CHANGELOG

This file is used to list changes made in each version of the `en_infra_aws` project.

### Version 1.4.0
Separate NAT instance configuration using a 'terraform module'.

### Version 1.3.0
Move terraform generated files: (.tfstate, .tfplan) into a separate `statefiles` directory.

Expand Down
3 changes: 2 additions & 1 deletion DevOpsVPC/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@ apply:
destroy:
terraform plan -destroy -var-file infrastructure.conf -out=statefiles/destroy.tfplan -state=statefiles/terraform.tfstate | tee -a logs/destroy.log
terraform apply statefiles/destroy.tfplan | tee -a logs/destroy.log
mv -f terraform.tfstate statefiles/destroy.tfstate
mv -f statefiles/terraform.tfstate statefiles/terraform.tfstate.old
mv -f terraform.tfstate statefiles/terraform.tfstate
5 changes: 5 additions & 0 deletions DevOpsVPC/infrastructure.conf
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,10 @@ vpc_public_subnets = ["10.10.10.0/24"]
ec2_custom_image = "" # ami-bcd95caa is the ubuntu 16.04 ami for 'us-east-1'
#-- otherwise ami is determined automatically
ec2_os = "CentOS Linux 7 x86_64"
#-- ssh user used to configure instance
ssh_user = "centos"
ssh_public_key_name = "terraform-ssh-key"
ssh_public_key_file = "~/.ssh/id_rsa.pub"
#-- ports open on the NAT instance
#-- becase we will also have VPN, we also open '45654'
nat_inbound_ports = "22,45654"
77 changes: 22 additions & 55 deletions DevOpsVPC/instances.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,74 +11,41 @@
# Provisions AWS instances used in our project
#


#-- EIP for NAT Instance
resource "aws_eip" "NatInstance" {
instance = "${aws_instance.NatInstance.id}"
vpc = true
}
#--
resource "aws_eip_association" "eip_assoc_NatInstance" {
instance_id = "${aws_instance.NatInstance.id}"
allocation_id = "${aws_eip.NatInstance.id}"
}

################## NAT INSTANCE
resource "aws_instance" "NatInstance" {
ami = "${replace(var.ec2_custom_image, "/^ami-.*/", "1") == 1 ? var.ec2_custom_image : data.aws_ami.centos.image_id}"
availability_zone = "${var.aws_azs[0]}"
instance_type = "t2.micro"
key_name = "${aws_key_pair.xanto.key_name}"
vpc_security_group_ids = ["${aws_security_group.AllowICMP.id}", "${aws_security_group.DefaultPub.id}"]
subnet_id = "${element(aws_subnet.public.*.id, count.index)}"

source_dest_check = false

root_block_device {
volume_type = "gp2"
volume_size = 8
delete_on_termination = true
}
tags = "${merge(var.default_tags, map("VPC", var.vpc_name), map("Name", format("%s_%s", var.vpc_name, "NATInstance")))}"
}

#-- workarround adding a triggered resource
#-- because of a circular dependency between
#-- eip and aws_instance
resource "null_resource" "preparation" {
triggers {
association_ip_address = "${aws_eip_association.eip_assoc_NatInstance.id}"
}
provisioner "remote-exec" {
inline = [
"sudo iptables -t nat -C POSTROUTING -o eth0 -s ${join(",", var.vpc_private_subnets)} -j MASQUERADE 2> /dev/null || sudo iptables -t nat -A POSTROUTING -o eth0 -s ${join(",", var.vpc_private_subnets)} -j MASQUERADE",
"echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf",
"echo 'net.ipv4.conf.eth0.send_redirects=0' | sudo tee -a /etc/sysctl.conf",
"echo 'net.netfilter.nf_conntrack_max=131072' | sudo tee -a /etc/sysctl.conf",
"sudo sysctl -p"
]
connection {
host = "${aws_eip.NatInstance.public_ip}"
user = "centos"
timeout = "30s"
private_key = "${file("/home/vagrant/.ssh/id_rsa")}"
}
}
module "nat" {
source = "../modules/nat"

number_of_instances = 1

instance_name = "NatVPN"
vpc_name = "${var.vpc_name}"
vpc_id = "${aws_vpc.vpc.id}"
instance_type = "t2.micro"
#-- we always want latest CentOS 7 AMI for NAT
ami_id = "${data.aws_ami.centos.image_id}"
subnet_id = "${join(",", aws_subnet.public.*.id)}"
private_subnets_cidr = "${join(",", aws_subnet.private.*.cidr_block)}"
inbound_ports = "${var.nat_inbound_ports}"
user_data = "../files/user-data/nat-vpn.cfg"
key_name = "${aws_key_pair.xanto.key_name}"
#-- assuming 'private key name' by removing the '.pub' extension
private_key_file = "${replace(var.ssh_public_key_file, ".pub", "")}"
sgs = "${aws_default_security_group.default.id},${aws_security_group.AllowICMP.id},${aws_security_group.DefaultPub.id}"
}

################## TEST INSTANCE
################### TEST INSTANCE
resource "aws_instance" "TestInstance" {
ami = "${replace(var.ec2_custom_image, "/^ami-.*/", "1") == 1 ? var.ec2_custom_image : data.aws_ami.centos.image_id}"
availability_zone = "${var.aws_azs[0]}"
instance_type = "t2.micro"
key_name = "${aws_key_pair.xanto.key_name}"
vpc_security_group_ids = ["${aws_security_group.AllowICMP.id}", "${aws_security_group.DefaultPrv.id}"]
vpc_security_group_ids = ["${aws_default_security_group.default.id}", "${aws_security_group.AllowICMP.id}", "${aws_security_group.DefaultPrv.id}"]
subnet_id = "${element(aws_subnet.private.*.id, count.index)}"

root_block_device {
volume_type = "gp2"
volume_size = 8
delete_on_termination = true
}
tags = "${merge(var.default_tags, map("VPC", var.vpc_name), map("Name", format("%s_%s", var.vpc_name, "TestInstance")))}"
tags = "${merge(var.default_tags, map("ManageRunningTime", "WorkingHoursStop"), map("VPC", var.vpc_name), map("Name", format("%s_%s", var.vpc_name, "TestInstance")))}"
}
6 changes: 3 additions & 3 deletions DevOpsVPC/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@

#-- EC2 Instances
output "NAT_instance_id" {
value = "${aws_instance.NatInstance.id}"
value = "${module.nat.instance_id}"
}

output "NAT_private_ip" {
value = "${aws_instance.NatInstance.private_ip}"
value = "${module.nat.private_ip}"
}

output "NAT_public_ip" {
value = "${aws_eip.NatInstance.public_ip}"
value = "${module.nat.public_ip}"
}

#--
Expand Down
40 changes: 32 additions & 8 deletions DevOpsVPC/security.tf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,29 @@ resource "aws_key_pair" "xanto" {
public_key = "${file(var.ssh_public_key_file)}"
}

#-- Default SG, can't be deleted. Only modified
resource "aws_default_security_group" "default" {
vpc_id = "${aws_vpc.vpc.id}"

#-- allow traffic between the resources
#-- that have this SG attached
ingress {
protocol = -1
self = true
from_port = 0
to_port = 0
}

#-- allow outside traffic
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = "${merge(var.default_tags, map("VPC", var.vpc_name), map("Name", format("%s_SG_%s", var.vpc_name, "default")))}"
}

#-- Security Groups
resource "aws_security_group" "AllowICMP" {
vpc_id = "${aws_vpc.vpc.id}"
Expand Down Expand Up @@ -53,14 +76,14 @@ resource "aws_security_group" "DefaultPub" {
cidr_blocks = ["0.0.0.0/0"]
}

# Outbound acces to anywhere
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}

# # Outbound acces to anywhere
# egress {
# from_port = 0
# to_port = 0
# protocol = "-1"
# cidr_blocks = ["0.0.0.0/0"]
# }
#
tags = "${merge(var.default_tags, map("VPC", var.vpc_name), map("Name", format("%s_SG_%s", var.vpc_name, "DefaultPub")))}"
}

Expand All @@ -87,3 +110,4 @@ resource "aws_security_group" "DefaultPrv" {

tags = "${merge(var.default_tags, map("VPC", var.vpc_name), map("Name", format("%s_SG_%s", var.vpc_name, "DefaultPrv")))}"
}

10 changes: 10 additions & 0 deletions DevOpsVPC/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ variable "enable_dns_hostnames" {
}

#-- Security
variable "ssh_user" {
description = "Name of the ssh user used for connecting to the remote instances"
type = "string"
}

variable "ssh_public_key_name" {
description = "Name of the SSH Key"
type = "string"
Expand All @@ -70,6 +75,11 @@ variable "ec2_os" {
type = "string"
}

#--
variable "nat_inbound_ports" {
description = "Allow following TCP ports to NAT instance."
default = "22,443"
}
##-- Tags for accounting
variable "default_tags" {
description = "A map of tags to add to all resources"
Expand Down
2 changes: 1 addition & 1 deletion DevOpsVPC/vpc.tf
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ resource "aws_route_table" "private" {

route {
cidr_block = "0.0.0.0/0"
instance_id = "${aws_instance.NatInstance.id}"
instance_id = "${module.nat.instance_id}"
# nat_gateway_id = "${element(split(",", var.nat_gateway_ids), count.index)}"
}

Expand Down
38 changes: 35 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ This project uses Terraform to accomplish this goal.
- [Security related](#security-related)
- [Instances related](#instances-related)
- [Other variables](#other-variables)
- [Modules](#modules)
- [NAT](#nat----modulesnat)
- [Usage](#usage)
- [Inspect the infrastructure](#make-plan)
- [Apply changes](#make-apply)
Expand Down Expand Up @@ -79,9 +81,7 @@ Project's data that can vary from one environment to another was exposed using v
This file is automatically loaded when invoking terraform by the `Makefile wrapper`. <br />
Refer to the `variables.tf` file in the `DevOpsVPC` directory for the default values.

[//]: # (Segment attributes by environment if multiple environments are created)

[//]: # (Copy section for multiple separated environments.)
[//]: # (Segment attributes by category.)

[//]: # (### Top Level Variables)
[//]: # (|Variable |Type |Description |Comments |)
Expand All @@ -103,10 +103,12 @@ Refer to the `variables.tf` file in the `DevOpsVPC` directory for the default va
| `vpc_public_subnets` | *List* | List of `CIDR blocks` for our public subnets.<br /> Must be in range of the `vpc_cidr`. | Mandatory |
| `enable_dns_support` | *Boolean* | Should be `true` if you want to use private DNS within the VPC. | Optional, defaults to `true` |
| `enable_dns_hostnames` | *Boolean* | Should be true if you want to use private DNS within the VPC. | Optional, defaults to `true` |
| `nat_inbound_ports` | *String* | Comma separated list of ports that will be opened on the public facing IP of the NAT instance.<br> Eg. SSH+VPN ports | Optional, defaults to `22,443` |

### Security related
|Variable |Type |Description |Comments |
|:---------|:----|:-----------|:--------|
| `ssh_user` | *String* | Name of the SSH used used to connect with during instance provisioning | Mandatory |
| `ssh_public_key_name` | *String* | Name of the `SSH Key` that will be uploaded into AWS and used for SSH into instances. | Mandatory |
| `ssh_public_key_file` | *String* | Location for the public ssh key file on your local workstation. | Mandatory |

Expand All @@ -121,6 +123,36 @@ Refer to the `variables.tf` file in the `DevOpsVPC` directory for the default va
|:---------|:----|:-----------|:--------|
| `default_tags` | *Map* | A map of tags to add to all resources for audit, identification, etc. | Optional |

---
[//]: # (Terraform Modules that this project provides.)

[//]: # (### Exposed variables to configure the module.)
[//]: # (|Variable |Type |Description |Comments |)
[//]: # (|:---------|:----|:-----------|:--------|)
[//]: # (| | | | |)

## Modules
### `NAT` -- `modules/nat/`
- Terraform module used to configure a EC2 instance that will serve as NAT Gateway/purpose for the instances that reside in the private subnet.
### Exposed variables:
|Variable |Type |Description |Comments |
|:---------|:----|:-----------|:--------|
| `instance_name` | *String* | Name of the Nat instance that will appear in AWS Console | Mandatory |
| `instance_type` | *String* | Type of the instance used that will serve as NAT Purpose | Optional |
| `vpc_name` | *String* | VPC name that the created instance will be assigned to. | Mandatory |
| `vpc_id` | *String* | VPC ID that the instance will be assigned to. | Mandatory |
| `subnet_id` | *String* | Subnet ID that will be `used for instance interface` creation. Eg. Public Subnet ID. | Mandatory |
| `private_subnets_cidr` | *String* | `CIDR of the private subnet` that the instance will do `NAT translation` for | Mandatory |
| `ami_id` | *String* | `AWS AMI ID` used for instance creation | Mandatory |
| `user_data` | *String* | `user_data` config used during instance creation | Mandatory |
| `sgs` | *String* | `Security groups IDs` that will be assigned to the NAT instance | Mandatory |
| `key_name` | *String* | `AWS Name of the ssh key` to be used during instance provisioning | Mandatory |
| `private_key_file` | *String* | Location for the private ssh key file that will be used to connect to the instance during provisioning | Mandatory |
| `number_of_instances` | *Integer* | Number of NAT instances to spawn | Optional, defaults to `1` |
| `root_volume_size` | *Integer* | Size in GBytes for the NAT instance root volume | Optional, defaults to `8` |
| `inbound_ports` | *String* | Comma separated list of ports that will be opened on the public facing IP of the NAT instance. Eg. SSH+VPN ports | Optional |


---
## **Usage**

Expand Down
22 changes: 22 additions & 0 deletions modules/nat/eip.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#
# Project Name:: en_infra_aws
# Module:: NAT
#
# Copyright (C) 2017 - Present
# Author: 'Mihai Vultur <mihai.vultur@___.com>'
#
# All rights reserved
#
# Description:
# Configures Elastic IP that will be associated with the NAT instance
#

resource "aws_eip" "NatInstance" {
instance = "${aws_instance.NatInstance.id}"
vpc = true
}
#--
resource "aws_eip_association" "eip_assoc_NatInstance" {
instance_id = "${aws_instance.NatInstance.id}"
allocation_id = "${aws_eip.NatInstance.id}"
}
36 changes: 36 additions & 0 deletions modules/nat/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#
# Project Name:: en_infra_aws
# Module:: NAT
#
# Copyright (C) 2017 - Present
# Author: 'Mihai Vultur <mihai.vultur@___.com>'
#
# All rights reserved
#
# Description:
# Creation of the EC2 instance that will serve as NAT Gateway
#

resource "aws_instance" "NatInstance" {
count = "${var.number_of_instances}"
ami = "${var.ami_id}"
instance_type = "${var.instance_type}"
subnet_id = "${element(split(",", var.subnet_id), count.index)}"
key_name = "${var.key_name}"

vpc_security_group_ids = [
"${split(",", var.sgs)}"
]

source_dest_check = false

root_block_device {
volume_type = "gp2"
volume_size = "${var.root_volume_size}"
delete_on_termination = true
}

tags = "${merge(map("ManageRunningTime", "WorkingHoursStop"), map("Provisioner", "terraform"), map("VPC", var.vpc_name), map("Name", format("%s_%s", var.vpc_name, var.instance_name)))}"

}

Loading

0 comments on commit b8862fa

Please sign in to comment.