Skip to content

Commit 7842de9

Browse files
Add awspec tests and supporting components (#6)
* Tests and fixtures for ALB components using awspec and test kitchen * S3 log bucket and policy rendering for logging now in place * root_principle_id added and referenced through a map for s3 bucket policy * string lists moved to native list types * default region removed * Restructured project templates to alb dir to add testing. This is a breaking change so upping major version. * Redundant examples dir removed * Updated documentation * All PR feedback addressed
1 parent a2fbc68 commit 7842de9

19 files changed

+343
-256
lines changed

.gitignore

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
*.tfvars*
1+
*.tfvars
22
*.tfstate*
33
.terraform
4-
**/Gemfile.lock
54
**/inspec.lock
65
*.gem
6+
.kitchen/
7+
.kitchen.local.yml
8+
Gemfile.lock

.kitchen.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
driver:
3+
name: terraform
4+
5+
provisioner:
6+
name: terraform
7+
directory: test/fixtures
8+
variable_files:
9+
- test/fixtures/terraform.tfvars
10+
11+
platforms:
12+
- name: aws
13+
14+
verifier:
15+
name: awspec
16+
# - name: terraform
17+
# format: doc
18+
# groups:
19+
# - name: local_tests
20+
# controls:
21+
# - local_alb
22+
23+
suites:
24+
- name: default
25+
verifier:
26+
name: awspec
27+
patterns:
28+
- test/integration/default/local_alb.rb

CHANGELOG.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,19 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

7-
## [Unreleased]
7+
## [1.0.0] - 2017-03-16
88
### Added
9+
* Tests and fixtures for ALB components using awspec and test kitchen
10+
* S3 log bucket and policy rendering for logging now in place
11+
* root_principle_id added and referenced through a map for s3 bucket policy
12+
* string lists moved to native list types
13+
* default region removed
914

1015
### Changed
16+
* Restructured project templates to alb dir to add testing. This is a breaking change so upping major version.
17+
* Redundant examples dir removed
18+
* Updated documentation
1119

1220
## [0.1.0] - 2017-03-09
1321
### Added
14-
- Initial release
15-
16-
### Changed
22+
* Initial release

Gemfile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
ruby '2.4.0'
2+
13
source 'https://rubygems.org/' do
2-
gem 'kitchen-terraform', '~> 0.6'
4+
gem 'test-kitchen'
5+
gem 'kitchen-terraform'
6+
gem 'awspec'
7+
gem 'kitchen-verifier-awspec'
8+
gem 'parseconfig'
39
end

README.md

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,19 @@ For an example of using ALB with ECS look no further than the [hashicorp example
2525

2626
## Input Variables
2727
* `alb_is_internal` - Determines if the ALB is externally facing or internal. (Optional; default: false)
28-
* `alb_name` - Name of the ALB as it appears in the AWS console. (Optional; default: my_alb)
28+
* `alb_name` - Name of the ALB as it appears in the AWS console. (Optional; default: my-alb)
2929
* `alb_protocols` - A comma delimited list of protocols the ALB will accept for incoming connections. Only HTTP and HTTPS are supported. (Optional; default: HTTPS)
3030
* `alb_security_groups` - A comma delimited list of security groups to attach to the ALB. (Required)
31+
* `aws_region` - Region to deploy our resources. (Required)
32+
* `aws_account_id` - The AWS account ID. (Required)
3133
* `backend_port` - Port on which the backing instances serve traffic. (Optional; default: 80)
3234
* `backend_protocol` - Protocol the backing instances use. (Optional; default: HTTP)
3335
* `certificate_arn` - . (Required if using HTTPS in `alb_protocols`)
3436
* `cookie_duration` - If sticky sessions via cookies are desired, set this variable to a value from 2 - 604800 seconds. (Optional)
3537
* `health_check_path` - Path for the load balancer to health check instances. (Optional; default: /)
3638
* `log_bucket` - S3 bucket where access logs should land. (Required)
3739
* `log_prefix` - S3 prefix within the `log_bucket` where logs should land. (Optional)
40+
* `principle_account_id` - A mapping of regions to principle account IDs used to send LB logs. (Should only change as regions are added)
3841
* `subnets` - ALB will be created in the subnets in this list. (Required)
3942
* `vpc_id` - Resources will be created in the VPC with this `id`. (Required)
4043

@@ -43,25 +46,39 @@ For an example of using ALB with ECS look no further than the [hashicorp example
4346
* `alb_dns_name` - DNS CNAME of the ALB created.
4447
* `alb_zone_id` - Route53 `zone_id` of the newly minted ALB.
4548
* `target_group_arn` - `arn` of the target group. Useful for passing to your Auto Scaling group module.
49+
* `principle_account_id` - the id of the AWS root user within this region. See [docs here]('http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html#attach-bucket-policy').
4650

4751
## Usage example:
48-
A full example set is contained in the [example directory](example/). Here's the gist:
49-
1. Set the input variables from above in [variables.tf](example/variables.tf).
50-
2. Define the ALB module using the following in your [main.tf](example/main.tf):
52+
A full example leveraging other community modules is contained in the [test/fixtures directory](test/fixtures). Here's the gist if you're using this module without:
53+
1. Set the input variables from above in [variables.tf](test/fixtures/variables.tf).
54+
2. Define the ALB module using the following in your [main.tf](test/fixtures/main.tf):
5155
```
5256
module "alb" {
53-
source = "github.com/brandoconnor/tf_aws_alb"
54-
alb_security_groups = "${var.security_group_id_list}"
57+
source = "github.com/terraform-community-modules/tf_aws_alb//alb"
58+
alb_security_groups = "${var.alb_security_groups}"
59+
aws_account_id = "${var.aws_account_id}"
60+
certificate_arn = "${var.certificate_arn}"
5561
log_bucket = "${var.log_bucket}"
56-
subnets = "${var.subnet_id_list}"
62+
log_prefix = "${var.log_prefix}"
63+
subnets = "${var.public_subnets}"
5764
vpc_id = "${var.vpc_id}"
5865
}
5966
```
6067
3. Always `terraform plan` to see your change before running `terraform apply`.
6168
4. Win the day!
6269

70+
## Testing
71+
This module has been packaged with [awspec]('https://github.com/k1LoW/awspec') tests through test kitchen. To run them:
72+
1. Install the prerequisites of rvm and ruby 2.4.0 via homebrew.
73+
2. Install bundler and the gems from our Gemfile:
74+
```
75+
gem install bundler; bundle install
76+
```
77+
3. Configure variables in `test/fixtures/terraform.tfvars`. An example of how this should look is in [terraform.tfvars.example](test/fixtures/terraform.tfvars.example).
78+
4. Test using `kitchen test` from the root of the repo.
79+
6380
## Contributing
64-
Report issues/questions/feature requests on in the [Issues](https://github.com/brandoconnor/tf_aws_alb/issues) section.
81+
Report issues/questions/feature requests on in the [Issues](https://github.com/terraform-community-modules/tf_aws_alb/issues) section.
6582

6683
Pull requests are welcome! Ideally create a feature branch and issue for every
6784
individual change you make. These are the steps:

alb/bucket_policy.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"Id": "Policy1429136655940",
3+
"Version": "2012-10-17",
4+
"Statement": [
5+
{
6+
"Sid": "Stmt1429136633762",
7+
"Action": [
8+
"s3:PutObject"
9+
],
10+
"Effect": "Allow",
11+
"Resource": "arn:aws:s3:::${log_bucket}/${log_prefix}/AWSLogs/${account_id}/*",
12+
"Principal": {
13+
"AWS": [
14+
"${principle_account_id}"
15+
]
16+
}
17+
}
18+
]
19+
}

alb/main.tf

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,84 @@
1-
### ALB resources with a switch - logging enabled/disabled
1+
### ALB resources
22

3-
resource "aws_alb" "alb_loging" {
3+
# TODO:
4+
# support not logging
5+
6+
data "template_file" "bucket_policy" {
7+
template = "${file("${path.module}/bucket_policy.json")}"
8+
9+
vars {
10+
log_bucket = "${var.log_bucket}"
11+
log_prefix = "${var.log_prefix}"
12+
account_id = "${var.aws_account_id}"
13+
principle_account_id = "${lookup(var.principle_account_id, var.aws_region)}"
14+
}
15+
}
16+
17+
resource "aws_alb" "main" {
418
name = "${var.alb_name}"
5-
subnets = ["${split(",", var.subnets)}"]
6-
security_groups = ["${split(",", var.alb_security_groups)}"]
19+
subnets = ["${var.subnets}"]
20+
security_groups = ["${var.alb_security_groups}"]
721
internal = "${var.alb_is_internal}"
822

923
access_logs {
1024
bucket = "${var.log_bucket}"
1125
prefix = "${var.log_prefix}"
1226
}
27+
}
1328

14-
count = "${var.log_bucket != "" && var.log_prefix != "" ? 1 : 0}"
29+
resource "aws_s3_bucket" "log_bucket" {
30+
bucket = "${var.log_bucket}"
31+
policy = "${data.template_file.bucket_policy.rendered}"
32+
force_destroy = true
1533
}
1634

17-
resource "aws_alb" "alb_nologing" {
18-
name = "${var.alb_name}"
19-
subnets = ["${split(",", var.subnets)}"]
20-
security_groups = ["${split(",", var.alb_security_groups)}"]
21-
internal = "${var.alb_is_internal}"
35+
resource "aws_alb_target_group" "target_group" {
36+
name = "${var.alb_name}-tg"
37+
port = "${var.backend_port}"
38+
protocol = "${upper(var.backend_protocol)}"
39+
vpc_id = "${var.vpc_id}"
40+
41+
health_check {
42+
interval = 30
43+
path = "${var.health_check_path}"
44+
port = "traffic-port"
45+
healthy_threshold = 3
46+
unhealthy_threshold = 3
47+
timeout = 5
48+
protocol = "${var.backend_protocol}"
49+
}
50+
51+
stickiness {
52+
type = "lb_cookie"
53+
cookie_duration = "${var.cookie_duration}"
54+
enabled = "${ var.cookie_duration == 1 ? false : true}"
55+
}
56+
}
57+
58+
resource "aws_alb_listener" "front_end_http" {
59+
load_balancer_arn = "${aws_alb.main.arn}"
60+
port = "80"
61+
protocol = "HTTP"
62+
63+
default_action {
64+
target_group_arn = "${aws_alb_target_group.target_group.id}"
65+
type = "forward"
66+
}
67+
68+
count = "${trimspace(element(split(",", var.alb_protocols), 1)) == "HTTP" || trimspace(element(split(",", var.alb_protocols), 2)) == "HTTP" ? 1 : 0}"
69+
}
70+
71+
resource "aws_alb_listener" "front_end_https" {
72+
load_balancer_arn = "${aws_alb.main.arn}"
73+
port = "443"
74+
protocol = "HTTPS"
75+
certificate_arn = "${var.certificate_arn}"
76+
ssl_policy = "ELBSecurityPolicy-2015-05"
77+
78+
default_action {
79+
target_group_arn = "${aws_alb_target_group.target_group.id}"
80+
type = "forward"
81+
}
2282

23-
count = "${(var.log_bucket == "" || var.log_prefix == "") ? 1 : 0}"
83+
count = "${trimspace(element(split(",", var.alb_protocols), 1)) == "HTTPS" || trimspace(element(split(",", var.alb_protocols), 2)) == "HTTPS" ? 1 : 0}"
2484
}

alb/outputs.tf

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,19 @@
1-
# this approach is not working just yet
2-
output "arn" {
3-
value = "${coalesce(aws_alb.alb_loging.arn, aws_alb.alb_nologing.arn) }"
4-
5-
/*value = "${aws_alb.alb_loging.arn}"*/
1+
output "alb_id" {
2+
value = "${aws_alb.main.id}"
63
}
74

8-
output "dns_name" {
9-
value = "${aws_alb.alb_loging.dns_name}"
10-
11-
/*value = "${coalesce(list("aws_alb.alb_loging.dns_name", "aws_alb.alb_nologing.dns_name")) }"*/
5+
output "alb_dns_name" {
6+
value = "${aws_alb.main.dns_name}"
127
}
138

14-
output "id" {
15-
value = "${aws_alb.alb_loging.id}"
16-
17-
/*value = "${coalesce(list("aws_alb.alb_loging.dns_name", "aws_alb.alb_nologing.dns_name")) }"*/
9+
output "alb_zone_id" {
10+
value = "${aws_alb.main.zone_id}"
1811
}
1912

20-
output "zone_id" {
21-
value = "${aws_alb.alb_loging.zone_id}"
13+
output "target_group_arn" {
14+
value = "${aws_alb_target_group.target_group.arn}"
15+
}
2216

23-
/*value = "${coalesce(list("aws_alb.alb_loging.dns_name", "aws_alb.alb_nologing.dns_name")) }"*/
17+
output "principle_account_id" {
18+
value = "${lookup(var.principle_account_id, var.aws_region)}"
2419
}

alb/variables.tf

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,49 @@ variable "alb_is_internal" {
99

1010
variable "alb_name" {
1111
description = "The name of the ALB as will show in the AWS EC2 ELB console."
12+
default = "my-alb"
13+
}
14+
15+
variable "alb_protocols" {
16+
description = "A comma delimited list of the protocols the ALB accepts. e.g.: HTTPS"
17+
default = "HTTPS"
1218
}
1319

1420
variable "alb_security_groups" {
1521
description = "A comma separated string of security groups with which we associate the ALB. e.g. 'sg-edcd9784,sg-edcd9785'"
22+
type = "list"
23+
}
24+
25+
variable "aws_region" {
26+
description = "AWS region to use."
27+
}
28+
29+
variable "aws_account_id" {
30+
description = "AWS account ID."
31+
}
32+
33+
variable "backend_port" {
34+
description = "The port the service on the EC2 instances listen on."
35+
default = 80
36+
}
37+
38+
variable "backend_protocol" {
39+
description = "The protocol the backend service speaks. Options: HTTP, HTTPS, TCP, SSL (secure tcp)."
40+
default = "HTTP"
41+
}
42+
43+
variable "certificate_arn" {
44+
description = "The ARN of the SSL Certificate. e.g. 'arn:aws:iam::123456789012:server-certificate/ProdServerCert'"
45+
}
46+
47+
variable "cookie_duration" {
48+
description = "If load balancer connection stickiness is desired, set this to the duration that cookie should be valid. If no stickiness is wanted, leave it blank. e.g.: 300"
49+
default = "1"
50+
}
51+
52+
variable "health_check_path" {
53+
description = "The URL the ELB should use for health checks. e.g. /health"
54+
default = "/"
1655
}
1756

1857
variable "log_bucket" {
@@ -23,6 +62,34 @@ variable "log_prefix" {
2362
description = "S3 prefix within the log_bucket under which logs are stored."
2463
}
2564

65+
variable "principle_account_id" {
66+
description = "A map of ELB/ALB root account numbers used to set up logging."
67+
68+
default = {
69+
us-east-1 = "127311923021"
70+
us-east-2 = "033677994240"
71+
us-west-1 = "027434742980"
72+
us-west-2 = "797873946194"
73+
ca-central-1 = "985666609251"
74+
eu-west-1 = "156460612806"
75+
eu-central-1 = "054676820928"
76+
eu-west-2 = "652711504416"
77+
ap-northeast-1 = "582318560864"
78+
ap-northeast-2 = "600734575887"
79+
ap-southeast-1 = "114774131450"
80+
ap-southeast-2 = "783225319266"
81+
ap-south-1 = "718504428378"
82+
sa-east-1 = "507241528517"
83+
us-gov-west-1 = "048591011584"
84+
cn-north-1 = "638102146993"
85+
}
86+
}
87+
2688
variable "subnets" {
27-
description = "A comma delimited list of subnets to associate with the ALB. e.g. 'subnet-1a2b3c4d,subnet-1a2b3c4e,subnet-1a2b3c4f'"
89+
description = "A list of subnets to associate with the ALB. e.g. ['subnet-1a2b3c4d','subnet-1a2b3c4e','subnet-1a2b3c4f']"
90+
type = "list"
91+
}
92+
93+
variable "vpc_id" {
94+
description = "VPC id where the ALB and other resources will be deployed."
2895
}

example/main.tf

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)