Skip to content

Commit

Permalink
Merge pull request #1 from Geartrixy/master
Browse files Browse the repository at this point in the history
Initial commit
  • Loading branch information
derBroBro authored Apr 8, 2018
2 parents e5dc656 + 9a80717 commit 601d209
Show file tree
Hide file tree
Showing 14 changed files with 763 additions and 1 deletion.
9 changes: 9 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
MIT License (MIT)

Copyright (c) 2018 Zoi TechCon GmbH

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
198 changes: 197 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,197 @@
# terraform-aws-alb
# AWS Application Load Balancer Module
Terraform module which sets up an application load balancer with either a HTTP listener, a HTTPS listener or both, and one or more target groups as required.
The idea behind this module is to support webservers hosting multiple sites for example a windows server running IIS.

The following resources are created:
* Application load balancer (internal or external)
* Load balancer listener(s) (HTTP, HTTPS or both)
* Target group(s) (HTTP, HTTPS or both)
* Security groups

## Legend
lb = load balancer
sg = security group
tg = target group


## Usage
### Specify this Module as Source
```hcl
module "alb" {
source = "git::https://github.com/zoitech/terraform-aws-alb.git"
# Or to specifiy a particular module version:
source = "git::https://github.com/zoitech/terraform-aws-alb.git?ref=v0.0.1"
```
### Target Group Arguments
The position of the values in each list corresponds to the value in the same position of the other list. E.g. a https request to "serv9.mysite.com" will be sent to the target group with name "Serv9-int-ssl" on port "10503".

Each of the three HTTP lists must contain an equal number of values, as is the case for when using HTTPS.
```hcl
# HTTP required arguments (if "lb_http_listener = true" ):
http_target_group_names = ["Serv1-int", "Serv2-int", "Serv3-int"]
http_target_group_ports = ["10500", "10501", "80"]
http_host_headers = ["serv1.mysite.com", "serv2.mysite.com", "serv3.mysite.com"]
http_health_check_interval = 15 #default = 30
http_health_check_path = "/status/load-balancer" #default = "/"
http_health_check_port = 1500 #default = "traffic-port"
http_health_check_timeout = 10 #default = 5
http_health_check_healthy_threshold = 2 #default = 3
http_health_check_unhealthy_threshold = 2 #default = 3
http_health_check_matcher = "200-299" #default = 200 (Success codes)
# HTTP optional arguments (if "lb_http_listener = true" ):
http_target_group_deregistration_delay = 30 #default = 300 (seconds)
http_target_group_stickiness_enabled = true #default set to false
http_target_group_stickiness_cookie_duration = 8640 #default 8640 seconds (1 day)
# HTTPS required arguments (if "lb_https_listener = true" ):
https_target_group_names = ["Serv1-int-ssl", "Serv2-int-ssl", "Serv9-int-ssl"]
https_target_group_ports = ["443", "8080", "10503"]
https_host_headers = ["serv1.mysite.com", "serv2.mysite.com", "serv9.mysite.com"]
https_health_check_interval = 15 #default = 30
https_health_check_path = "/status/load-balancer" #default = "/"
https_health_check_port = 1500 #default = "traffic-port"
https_health_check_timeout = 10 #default = 5
https_health_check_healthy_threshold = 2 #default = 3
https_health_check_unhealthy_threshold = 2 #default = 3
https_health_check_matcher = "200-299" #default = 200 (Success codes)
# HTTPS optional arguments (if "lb_https_listener = true" ):
https_target_group_deregistration_delay = 30 #default = 300 (seconds)
https_target_group_stickiness_enabled = true #default set to false
https_target_group_stickiness_cookie_duration = 8640 #default 8640 seconds (1 day)
# VPC ID and the target instance are valid for both target groups and need only be set once:
vpc_id = "vpc-a01234bc"
target_id = "i-00123456789123abc"
```


### Load Balancer Required Arguments
#### Internal or External
To configure the load balancer for internal or external (public) use:

```hcl
lb_internal = false #default = true
```
#### Load Balancer Listener Protocols
The following determines what kind of listener(s) will be applied to the load balancer:
* HTTP
* HTTPS
* or both

```hcl
lb_http_listener = true #default = true
lb_https_listener = true #default = false
```
#### Load Balancer Listener Ports
HTTP/HTTPS listener port of the load balancer depending on what kind of listener(s) are selected:
```hcl
lb_http_listener_port = 8080 #default = 80
lb_https_listener_port = 443 #default = 443
```

#### SSL Certificate
If a HTTPS listener is being used, set the SSL certificate:
```hcl
certificate_arn = "arn:aws:acm:eu-central-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
```

#### Load Balancer Name

Set the load balancer name:
```hcl
lb_name = "Internal Services"
```


#### Subnets

Specifying the subnets for the load balancer:

```hcl
# If the load balancer is internal, configure lb_private_subnet_ids:
lb_private_subnet_ids = ["subnet-12345678", "subnet-abc87654"]
# If the load balancer is external, configure lb_public_subnet_ids:
lb_public_subnet_ids = ["subnet-98765432", "subnet-98765cba"]
```
#### Security Groups
Four security groups are created by default.

An empty security group is created and attached to the load balancer, which can be used later as the security group source in other security groups to allow traffic into the instance:

* "Group-ALB-${var.lb_name}"

The following security group permits all traffic outbound from the load balancer by default:

* "Rule-all-out-all"

A HTTP listener traffic in security group is created to allow HTTP traffic in only from specific sources. The name of the security group is configured as follows:

* "Rule-allow-${var.lb_source_traffic_name}-in-HTTP"

The variable "lb_source_traffic_name" should be set to a location or department where the source traffic is coming from:

```hcl
lb_source_traffic_name = "Human-Resources"
```

Alternatively the variable "var.lb_sg_http_name" can be set to fully customize the name of the security group. If this variable is set, "var.lb_source_traffic_name" is no longer required:

```hcl
lb_sg_http_name = "My-http-security-group-name"
```
The same applies for the HTTPS security group name:

```hcl
lb_sg_https_name = "My-https-security-group-name"
```

By default **all IP addresses are permitted** for both the HTTP and HTTPS security group. To specify specific IP ranges (or CIDR blocks) set the following variables:

```hcl
rule_allow_lb_http_listener_traffic_in_cidr_blocks = ["172.16.0.0/16", "192.168.0.0/24"]
rule_allow_lb_https_listener_traffic_in_cidr_blocks = ["172.16.0.0/16", "192.168.0.0/24"]
```

#### Load Balancer Optional Arguments

Additional security groups can be added to the load balancer:

```hcl
lb_security_groups = ["sg-12345678", "sg-abc87654"]
```
Idle timeout (default = 60) for the load balancer, defining if http2 is enabled (default = true) and enabling deletion protection (default = false) can also be set as follows:
```hcl
lb_idle_timeout = 60
lb_enable_http2 = true
lb_enable_deletion_protection = false
```
##### Prefixes and Suffixes (not Latin words ;-))
Can be set when there is a standard naming convention in use. They are applied to the name of the load balancer and target group resources (default = null/empty)
```hcl
prefix = "P-"
suffix = "-HR"
```





## Authors
Module managed by [Zoi](https://github.com/zoitech).

## License
MIT License. See LICENSE for full details.
13 changes: 13 additions & 0 deletions alb.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
resource "aws_lb" "application_loadbalancer" {
### Required Arguments ###
name = "${var.prefix}${var.lb_name}${var.suffix}"
internal = "${var.lb_internal}"
load_balancer_type = "application"
security_groups = ["${local.lb_security_groups}"]
subnets = ["${local.lb_subnet_ids}"]

### Optional Arguments ###
idle_timeout = "${var.lb_idle_timeout}"
enable_http2 = "${var.lb_enable_http2}"
enable_deletion_protection = "${var.lb_enable_deletion_protection}"
}
29 changes: 29 additions & 0 deletions alb_http_listeners.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Create http listener for the loadbalancer if "var.lb_http_listener == true"
resource "aws_lb_listener" "application_loadbalancer_listener_http" {
count = "${var.lb_http_listener}"
load_balancer_arn = "${aws_lb.application_loadbalancer.arn}"
port = "${var.lb_http_listener_port}"
protocol = "HTTP"

default_action {
target_group_arn = "${aws_lb_target_group.tg_http.0.arn}"
type = "forward"
}
}

# Create http listener rules
resource "aws_lb_listener_rule" "http_host_based_routing" {
count = "${var.lb_http_listener ? "${length(var.http_host_headers) == "${length(var.http_target_group_names)}" ? "${length(var.http_host_headers)}" : 0}" :0}"

listener_arn = "${aws_lb_listener.application_loadbalancer_listener_http.arn}"

action {
type = "forward"
target_group_arn = "${element(aws_lb_target_group.tg_http.*.arn, count.index)}"
}

condition {
field = "host-header"
values = ["${element(var.http_host_headers, count.index)}"]
}
}
31 changes: 31 additions & 0 deletions alb_https_listeners.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Create https listener for the loadbalancer if "var.lb_https_listener == true"
resource "aws_lb_listener" "application_loadbalancer_listener_https" {
count = "${var.lb_https_listener}"
load_balancer_arn = "${aws_lb.application_loadbalancer.arn}"
port = "${var.lb_https_listener_port}"
protocol = "HTTPS"

default_action {
target_group_arn = "${aws_lb_target_group.tg_https.0.arn}"
type = "forward"
}

certificate_arn = "${var.certificate_arn}"
}

# Create https listener rules
resource "aws_lb_listener_rule" "https_host_based_routing" {
count = "${var.lb_https_listener ? "${length(var.https_host_headers) == "${length(var.https_target_group_names)}" ? "${length(var.https_host_headers)}" : 0}" :0}"

listener_arn = "${aws_lb_listener.application_loadbalancer_listener_https.arn}"

action {
type = "forward"
target_group_arn = "${element(aws_lb_target_group.tg_https.*.arn, count.index)}"
}

condition {
field = "host-header"
values = ["${element(var.https_host_headers, count.index)}"]
}
}
45 changes: 45 additions & 0 deletions http_target_groups.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#### Create http target group(s) ####
resource "aws_lb_target_group" "tg_http" {
# Check the number of http target group names matches the number of http target group ports.
# If check is ok creates the number of http target group resources based on the number of http target group names
count = "${var.lb_http_listener ? "${length(var.http_target_group_names) == "${length(var.http_target_group_ports)}" ? "${length(var.http_target_group_names)}" : 0}" :0}"

### Required Arguments ###
name = "${var.prefix}${element(var.http_target_group_names, count.index)}${var.suffix}" # default prefix/suffix = "". Default target group name = ["http-target-group"] N.B. 32 Character limit with prefix/suffix
port = "${element(var.http_target_group_ports, count.index)}" # default = [80]
protocol = "HTTP"
vpc_id = "${var.vpc_id}"

health_check {
interval = "${var.http_health_check_interval}" #default = 30
path = "${var.http_health_check_path}" #default = "/"
port = "${var.http_health_check_port}" #default = "traffic-port"
protocol = "HTTP"
timeout = "${var.http_health_check_timeout}" #default = 5
healthy_threshold = "${var.http_health_check_healthy_threshold}" #default = 3
unhealthy_threshold = "${var.http_health_check_unhealthy_threshold}" #default = 3
matcher = "${var.http_health_check_matcher}" #default = 200
}

target_type = "instance"

### Optional Arguments ###
deregistration_delay = "${var.http_target_group_deregistration_delay}" # default = 300.

stickiness {
enabled = "${var.http_target_group_stickiness_enabled}" # default set to false
type = "lb_cookie" # default = lb_cookie. Only possible value for applicatoin load balancer
cookie_duration = "${var.http_target_group_stickiness_cookie_duration}" # default 8640 seconds (1 day).
}

#tags = https://github.com/hashicorp/terraform/issues/15226
}

# Attach target to http target group(s)
resource "aws_lb_target_group_attachment" "attach_http_tg" {
count = "${var.lb_http_listener ? "${length(var.http_target_group_names) == "${length(var.http_target_group_ports)}" ? "${length(var.http_target_group_names)}" : 0}" :0}"

target_group_arn = "${element(aws_lb_target_group.tg_http.*.arn, count.index)}"
target_id = "${var.target_id}"
port = "${element(var.http_target_group_ports, count.index)}"
}
43 changes: 43 additions & 0 deletions https_target_groups.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#### Create https target group(s) ####
resource "aws_lb_target_group" "tg_https" {
# Check the number of https target group names matches the number of https target group ports.
# If check is ok creates the number of https target group resources based on the number of https target group names
count = "${var.lb_https_listener ? "${length(var.https_target_group_names) == "${length(var.https_target_group_ports)}" ? "${length(var.https_target_group_names)}" : 0}" :0}"

### Required Arguments ###
name = "${var.prefix}${element(var.https_target_group_names, count.index)}${var.suffix}" # default prefix/suffix = "". Default target group name = ["https-target-group"] N.B. 32 Character limit with prefix/suffix
port = "${element(var.https_target_group_ports, count.index)}" # default = [443]
protocol = "HTTPS"
vpc_id = "${var.vpc_id}"

health_check {
interval = "${var.https_health_check_interval}" #default = 30
path = "${var.https_health_check_path}" #default = "/"
port = "${var.https_health_check_port}" #default = "traffic-port"
protocol = "HTTPS"
timeout = "${var.https_health_check_timeout}" #default = 5
healthy_threshold = "${var.https_health_check_healthy_threshold}" #default = 3
unhealthy_threshold = "${var.https_health_check_unhealthy_threshold}" #default = 3
matcher = "${var.https_health_check_matcher}" #default = 200
}

target_type = "instance"

### Optional Arguments ###
deregistration_delay = "${var.https_target_group_deregistration_delay}" # default = 300.

stickiness {
enabled = "${var.https_target_group_stickiness_enabled}" # default set to false
type = "lb_cookie" # default = lb_cookie. Only possible value for applicatoin load balancer
cookie_duration = "${var.https_target_group_stickiness_cookie_duration}" # default 8640 seconds (1 day).
}
}

# Attach target to https target group(s)
resource "aws_lb_target_group_attachment" "attach_https_tg" {
count = "${var.lb_https_listener ? "${length(var.https_target_group_names) == "${length(var.https_target_group_ports)}" ? "${length(var.https_target_group_names)}" : 0}" :0}"

target_group_arn = "${element(aws_lb_target_group.tg_https.*.arn, count.index)}"
target_id = "${var.target_id}"
port = "${element(var.https_target_group_ports, count.index)}"
}
12 changes: 12 additions & 0 deletions locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
locals {
# Security groups
lb_security_groups_for_http = ["${aws_security_group.lb_group.id}", "${aws_security_group.rule_all_out.id}", "${aws_security_group.lb_http_listener_traffic_in.id}", "${var.lb_security_group_ids}"]
lb_security_groups_for_https = ["${aws_security_group.lb_group.id}", "${aws_security_group.rule_all_out.id}", "${aws_security_group.lb_https_listener_traffic_in.id}", "${var.lb_security_group_ids}"]
lb_security_groups_for_http_https = ["${aws_security_group.lb_group.id}", "${aws_security_group.rule_all_out.id}", "${aws_security_group.lb_http_listener_traffic_in.id}", "${aws_security_group.lb_https_listener_traffic_in.id}", "${var.lb_security_group_ids}"]
lb_security_groups = ["${split(",", var.lb_http_listener ? var.lb_https_listener ? join(",", local.lb_security_groups_for_http_https) : join(",", local.lb_security_groups_for_http) : join(",", local.lb_security_groups_for_https))}"]

# Subnet IDs
lb_private_subnet_ids = ["${var.lb_private_subnet_ids}"]
lb_public_subnet_ids = ["${var.lb_public_subnet_ids}"]
lb_subnet_ids = ["${split(",", var.lb_internal ? join(",", local.lb_private_subnet_ids) : join(",", local.lb_public_subnet_ids))}"]
}
Loading

0 comments on commit 601d209

Please sign in to comment.