Skip to content

Commit

Permalink
0.2.0 -
Browse files Browse the repository at this point in the history
 [GH-1] aws flow log creation
 [GH-3] NATs are still allocated when 0 private subnets are selected
 Added support for optional CloudWatch auto recovery alarms on NAT instances
 Update examples
 Renamed Readme.md to README.md
 Updated terraform version for build
 Update licenses
  • Loading branch information
robertys10 committed Oct 28, 2015
1 parent 3862399 commit 0f959cc
Show file tree
Hide file tree
Showing 13 changed files with 667 additions and 205 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
## 0.2.0 (Oct 27, 2015)
Fixes/Features
Issue [GH-1] - VPC:Base - Add aws flow log creation. (enhancement)
Issue [GH-3] - NATs are still allocated when 0 private subnets are selected (bug)
Renamed Readme.md to README.md
Updated license
Added support for optional auto recovery CloudWatch alarms for NAT instances
## 0.1.0 (Oct 21, 2015)
* Initial Release
573 changes: 372 additions & 201 deletions LICENSE

Large diffs are not rendered by default.

177 changes: 177 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# Terraform AWS VPC Stack #
[![Circle CI](https://circleci.com/gh/unifio/terraform-aws-vpc/tree/master.svg?style=svg)](https://circleci.com/gh/unifio/terraform-aws-vpc/tree/master)

Module stack that supports full AWS VPC deployment. Users can provision a VPC with optional support for
DHCP Options Sets, Virtual Private Gateway creation, and provision one or more availability zones (AZs) each coming with its own NAT setup, external facing (DMZ) and private (LAN) subnets. AWS flow logs are setup VPC wide, and there is optional support for auto recovery on the AZ NAT instances using CloudWatch alarms.

## Base Module ##

The Base module provisions the VPC, attaches an Internet Gateway, and creates NAT Security Group and DMZ Routing table

### Input Variables ###

- `stack_item_label` - Short form identifier for this stack. This value is used to create the "Name" resource tag for resources created by this stack item, and also serves as a unique key for re-use.
- `stack_item_fullname` - Long form descriptive name for this stack item. This value is used to create the "application" resource tag for resources created by this stack item.
- `vpc_cidr` - CIDR block for the VPC.
- `enable_dns` - (Optional) A boolean flag to enable/disable DNS support in the VPC. Defaults true.
- `enable_hostnames` - (Optional) A boolean flag to enable/disable DNS hostnames in the VPC. Defaults false.
- `lan_cidr` - Comma separated list of CIDR blocks to be given ingress access to NAT boxes in each subnet.

### Usage ###

```js
module "vpc_base" {
source = "github.com/unifio/terraform-aws-vpc//base"

stack_item_label = "mystack1"
stack_item_fullname = "Stack Item Description"
vpc_cidr = "10.10.0.0/22"
enable_dns = true
enable_hostnames = false
lan_cidr = "10.10.2.0/25,10.10.2.128/25,10.10.3.0/25"
}
```
### Outputs ###

- `vpc_id` - ID of the VPC
- `igw_id` - ID of the Internet gateway
- `rt_dmz_id` - ID of the DMZ routing table
- `nat_sg_id` - ID of NAT security group

## DHCP module ##

The DHCP module provisions a DHCP options resource and associates it with the specified VPC resource.

### Input Variables ###

- `vpc_id` - ID of the VPC to associate the DHCP Options Set with.
- `stack_item_label` - Short form identifier for this stack. This value is used to create the "Name" resource tag for resources created by this stack item, and also serves as a unique key for re-use.
- `stack_item_fullname` - Long form descriptive name for this stack item. This value is used to create the "application" resource tag for resources created by this stack item.
- `domain_name` - (Optional) the suffix domain name to use by default when resolving non Fully Qualified Domain Names. In other words, this is what ends up being the search value in the /etc/resolv.conf file.
- `name_servers` - (Optional) List of name servers to configure in /etc/resolv.conf.
- `ntp_servers` - (Optional) List of NTP servers to configure.
- `netbios_name_servers` - (Optional) List of NETBIOS name servers.
- `netbios_node_type` - (Optional) The NetBIOS node type (1, 2, 4, or 8). AWS recommends to specify 2 since broadcast and multicast are not supported in their network. For more information about these node types, see RFC 2132. Defaults to 2.

### Usage ###

The usage examples may assume that previous modules in this stack have already been declared, such as the base module, instantiated as "vpc_base". This declaration is not necessary, but does promote a consistent and maintainable standard.

```js

module "dhcp" {
source = "github.com/terraform-aws-vpc//dhcp"

vpc_id = "${module.vpc_base.vpc_id}"
stack_item_label = "mystack1"
stack_item_fullname = "myname"
domain_name = "mydomain.com"
name_servers = "10.128.8.10"
ntp_servers = "10.128.8.10"
netbios_name_servers = "10.128.8.10"
netbios_node_type = 2
}
```
### Outputs ###

- `dhcp_id` - ID of the DHCP Options set

## VPG Module ##

Creates a VPC VPN Gateway

### Input Variables

- `vpc_id` - The VPC to associate the VPG with.
- `stack_item_label` - Short form identifier for this stack. This value is used to create the "Name" resource tag for resources created by this stack item, and also serves as a unique key for re-use.
- `stack_item_fullname` - Long form descriptive name for this stack item. This value is used to create the "application" resource tag for resources created by this stack item.

### Usage

The usage examples may assume that previous modules in this stack have already been declared, such as the base module, instantiated as "vpc_base". This declaration is not necessary, but does promote a consistent and maintainable standard.

```js

module "vpg" {
source = "github.com/terraform-aws-vpc//vpg"

vpc_id = "${module.vpc_base.vpc_id}"
stack_item_fullname = "Stack Item Description"
stack_item_label = "mystack1"
}
```

### Outputs ###

- `vpg_id` - ID of the newly created Virtual Private Gateway

## AZ Module ##

In each Availability Zone provided, this module provisions a NAT instance, and creates subnets and routing tables for a public (DMZ) and private (LAN) sub networks. The remote access information for the NAT instance is output to user data.

### Input Variables ###

- `stack_item_label` - Short form identifier for this stack. This value is used to create the "Name" resource tag for resources created by this stack item, and also serves as a unique key for re-use.
- `stack_item_fullname` - Long form descriptive name for this stack item. This value is used to create the "application" resource tag for resources created by this stack item.
- `vpc_id` - ID of the VPC to use.
- `region` - AWS region to deploy in.
- `az` - Comma separated list of Availability Zones (AZs) in which to create the previously described infrastructure.
- `dmz_cidr` -Comma separated list of CIDR blocks to be used for DMZ subnet. This list should correspond 1:1 to each AZ.
- `lan_cidr` - Comma separated list of CIDR blocks to be used for LAN subnet. This list should correspond 1:1 to each AZ.
- `lans_per_az` - The number of private subnets to be provisioned per AZ. You will need to double the CIDR blocks specified in the `lan_cidr` variable for each increase in this value.
- `enable_dmz_public_ips` - Specify true to indicate that instances launched into the subnet should be assigned a public IP address. Defaults to true.
- `rt_dmz_id` - ID of the DMZ route table for this VPC.
- `ami` - AWS AMI to use when creating NAT instance in each AZ.
- `instance_type` - EC2 instance type to be used.
- `key_name` - The key name to use for the NAT instances.
- `nat_sg_id` - ID of the NAT security group.
- `user_data_template` - Template to be used to generate user data. Default is "templates/user_data.tpl". This template will be passed the following variables:
* hostname - Name of NAT instance for the current AZ.
* fqdn - Fully Qualified Domain Name for the NAT instance
* ssh_user - SSH username to be given NAT access via SSH
- `domain` - Domain name
- `ssh_user` - Username to use when enabling SSH access to NAT instance. Default is ec2-user.
- `nat_auto_recovery` - Set to 0 or 1. 0 disables and 1 enables. If enabled, CloudWatch alarms will be created that will automatically recover the NAT instances, preserving its instance id, ip, etc. in the case of system failure. Default is 1 (enabled). Please check that the AMI used for the NAT supports recovery of its instances.
- `period` - The period in seconds over which a system failure in the NAT instance occurs. Not used if enable_nat_auto_recovery is 0.
- `evaluation_periods` - The number of consecutive periods in which the system failure must occur for the alarm to fire. Not used if enable_nat_auto_recovery is 0.


### Usage ###

The usage examples may assume that previous modules in this stack have already been declared, such as the base module, instantiated as "vpc_base". This declaration is not necessary, but does promote a consistent and maintainable standard.

```js
module "AZs" {
source = "github.com/unifio/terraform-aws-vpc//az"

stack_item_label = "mystack1"
stack_item_fullname = "Stack Item Description"
vpc_id = "${module.vpc_base.vpc_id}"
region = "us-west-2"
az = "a,b"
dmz_cidr = "10.10.0.0/25,10.10.0.128/25,10.10.1.0/25"
lan_cidr = "10.10.2.0/25,10.10.2.128/25,10.10.3.0/25"
lans_per_az = "1"
enable_dmz_public_ips = "true"
rt_dmz_id = "${module.vpc_base.rt_dmz_id}"
ami = "ami-xxxxxxxx"
instance_type = "t2.micro"
key_name = "ops"
nat_sg_id = "${module.vpc_base.nat_sg_id}"
user_data_template = "templates/user_data.tpl"
domain - "mydomain.com"
ssh_user = "ec2-user"
}
```
### Outputs ###

- `lan_id` - List of subnet IDs of the LAN subnetworks. The order and association of the IDs match the order of the availability zones passed to the module.
- `dmz_id` - List of subnet IDs of the DMZ subnetworks. The order and association of the IDs match the order of the availability zones passed to the module.

## Examples ##

See the [examples](examples) directory for a complete set of example source files.

## License ##

MPL 2.0. See LICENSE for full details.
4 changes: 3 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ DHCP Options Sets, Virtual Private Gateway creation, and provision one or more a

## Base Module ##

The Base module provisions the VPC, attaches an Internet Gateway, and creates NAT Security Group and DMZ Routing table
The Base module provisions the VPC, attaches an Internet Gateway, and creates NAT Security Group, DMZ Routing table, and creates a CloudWatch group, IAM role, and AWS flow log. The flow log is configured to capture all traffic (ALLOW and DENY) over the entire VPC.

### Input Variables ###

Expand All @@ -17,6 +17,7 @@ The Base module provisions the VPC, attaches an Internet Gateway, and creates NA
- `enable_hostnames` - (Optional) A boolean flag to enable/disable DNS hostnames in the VPC. Defaults false.
- `lan_cidr` - Comma separated list of CIDR blocks to be given ingress access to NAT boxes in each subnet.


### Usage ###

```js
Expand All @@ -37,6 +38,7 @@ module "vpc_base" {
- `igw_id` - ID of the Internet gateway
- `rt_dmz_id` - ID of the DMZ routing table
- `nat_sg_id` - ID of NAT security group
- `flow_log_id` - ID of the AWS flow log

## DHCP module ##

Expand Down
28 changes: 26 additions & 2 deletions az/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ resource "template_file" "user_data" {

### Provisions NAT instance
resource "aws_instance" "nat" {
count = "${length(split(",",var.az))}"
ami = "${var.ami}"
count = "${length(split(",",var.az)) * element(split(",",var.lans_per_az_is_zero),var.lans_per_az)}"
instance_type = "${var.instance_type}"
ami = "${var.ami}"
key_name = "${var.key_name}"
vpc_security_group_ids = ["${var.nat_sg_id}"]
subnet_id = "${element(aws_subnet.dmz.*.id,count.index)}"
Expand All @@ -51,6 +51,30 @@ resource "aws_instance" "nat" {
user_data = "${element(template_file.user_data.*.rendered, count.index)}"
}

## Add CloudWatch alarm to recover instance in the case of a fault
resource "aws_cloudwatch_metric_alarm" "recover_alarm" {
## The use of the lans_per_az_is_zero list is to map any nonzero variable onto a value of 1
## and a value of zero variable onto 0. This is not a foolproof way to do this, since
## technically you need an index for every conceivable value, so instead we count on the following:
## 1) We have 20 indices, which allows the user up to 20 lans_per_az, which should be plenty
## 2) If the user accidentally puts some random value in for lans_per_az or nat_auto_recovery the modulo
## ensures that in the worst case don't get a giant multiplier
count = "${length(split(",",var.az)) * element(split(",",var.lans_per_az_is_zero),var.lans_per_az) * element(split(",",var.lans_per_az_is_zero),var.nat_auto_recovery)}"
alarm_name = "${var.stack_item_label}-nat-${count.index}-alarm"
dimensions = {
InstanceId = "${element(aws_instance.nat.*.id, count.index)}"
}
metric_name = "StatusCheckFailed"
namespace = "AWS/EC2"
statistic = "Average"
comparison_operator = "GreaterThanThreshold"
threshold = "0"
period = "${var.period}"
evaluation_periods = "${var.evaluation_periods}"
alarm_description = "Recover instance upon series of StatusCheckFailed events"
alarm_actions = [ "arn:aws:automate:${var.region}:ec2:recover" ]
}

## Provisions LAN resources

### Provisions subnet
Expand Down
14 changes: 14 additions & 0 deletions az/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ variable "lan_cidr" {}
variable "enable_dmz_public_ips" {
default = true
}
variable "nat_auto_recovery" {
default = "1"
}
variable "period" {
default = 60
}
variable "evaluation_periods" {
default = 2
}
variable "lans_per_az" {
default = "1"
}
Expand All @@ -32,3 +41,8 @@ variable "domain" {}
variable "ssh_user" {
default = "ec2-user"
}

## private/hidden variables
variable "lans_per_az_is_zero" {
default = "0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"
}
55 changes: 55 additions & 0 deletions base/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,58 @@ resource "aws_security_group" "nat_sg" {
cidr_blocks = ["0.0.0.0/0"]
}
}

# Provision aws_flow_log with reasonable initial settings

resource "aws_cloudwatch_log_group" "flow_log_group" {
name = "${var.stack_item_label}FlowLogGroup"
}

resource "aws_iam_role" "flow_log_role" {
name = "${var.stack_item_label}FlowLogRole"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "vpc-flow-logs.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}

resource "aws_iam_role_policy" "flow_log_role_policies" {
name = "${var.stack_item_label}FlowLogPolicy"
role = "${aws_iam_role.flow_log_role.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
EOF
}

resource "aws_flow_log" "flow_log" {
log_group_name = "${var.stack_item_label}FlowLogGroup"
iam_role_arn = "${aws_iam_role.flow_log_role.arn}"
vpc_id = "${aws_vpc.vpc.id}"
traffic_type = "ALL"
}
4 changes: 4 additions & 0 deletions base/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@ output "rt_dmz_id" {
output "nat_sg_id" {
value = "${aws_security_group.nat_sg.id}"
}

output "flow_log_id" {
value = "${aws_flow_log.flow_log.id}"
}
2 changes: 1 addition & 1 deletion circle.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
machine:
environment:
TF_VERSION: 0.6.4
TF_VERSION: 0.6.6
TF_URL: https://dl.bintray.com/mitchellh/terraform/terraform_${TF_VERSION}_linux_amd64.zip
dependencies:
pre:
Expand Down
1 change: 1 addition & 0 deletions examples/basic/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ module "vpc_az" {
user_data_template = "${var.user_data_template}"
domain = "${var.domain_name}"
ssh_user = "${var.ssh_user}"
nat_auto_recovery = "${var.nat_auto_recovery}"
}
3 changes: 3 additions & 0 deletions examples/basic/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ variable "lan_cidr" {
variable "lans_per_az" {
default = "1"
}
variable "nat_auto_recovery" {
default = "1"
}
variable "lan_access_cidr" {
default = "10.10.2.0/23"
}
Expand Down
1 change: 1 addition & 0 deletions examples/full_stack/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,5 @@ module "vpc_az" {
user_data_template = "${var.user_data_template}"
domain = "${var.domain_name}"
ssh_user = "${var.ssh_user}"
nat_auto_recovery = "${var.nat_auto_recovery}"
}
3 changes: 3 additions & 0 deletions examples/full_stack/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ variable "lan_cidr" {
variable "lans_per_az" {
default = "1"
}
variable "nat_auto_recovery" {
default = "1"
}
variable "lan_access_cidr" {
default = "10.10.2.0/23"
}
Expand Down

0 comments on commit 0f959cc

Please sign in to comment.