Skip to content

Commit e03488b

Browse files
committed
feat: s3 bucket sub module integration into root module
Store ALB access and connection logs into S3 bucket in the root module.
1 parent 55f3690 commit e03488b

File tree

8 files changed

+244
-15
lines changed

8 files changed

+244
-15
lines changed

examples/complete/.header.md

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,59 @@
33
Configuration in this directory creates:
44

55
- ECS Service in a pre-configured ECS Cluster and corresponding ECS Capacity Providers
6-
- Internet-facing Application Load Balancer to access the deployed services, and
7-
- ACM to generate an Amazon-issued certificate for a base domain, and then create a Route53 A-type record with an endpoint
6+
- Internet-facing Application Load Balancer to access the deployed services with S3 bucket for storing access and connection logs, and
7+
- ACM to generate and validate an Amazon-issued certificate for a base domain
8+
9+
## Example `tfvars` Configuration
10+
11+
```tf
12+
vpc_id = "vpc-0123456789abcdefg"
13+
service_network_configuration_security_groups = ["sg-0123456789abcdefg"]
14+
private_subnets = ["subnet-0123456789abcdefg", "subnet-0123456789abcdefg"]
15+
public_subnets = ["subnet-0123456789abcdefg", "subnet-0123456789abcdefg"]
16+
17+
cluster_name = "your-cluster-name"
18+
container_name = "your-container-name"
19+
service_desired_count = 123
20+
container_image = "your-container-image:version"
21+
container_port = 123
22+
container_cpu = 123
23+
container_memory = 123
24+
container_essential = true
25+
container_port_mappings = [
26+
{
27+
name = "your-port-mapping-name"
28+
containerPort = 123
29+
hostPort = 123
30+
protocol = "your-port-mapping-protocol"
31+
}
32+
]
33+
container_readonly_root_filesystem = false
34+
35+
asg_arn = "arn:aws:autoscaling:your-region:01234567890:autoScalingGroup:abcdefgh-ijkl-mnop-qrst-uvwxyz012345:autoScalingGroupName/your-autoscaling-group-name"
36+
capacity_provider_name = "your-capacity-provider-name"
37+
capacity_provider_managed_scaling = {
38+
status = "ENABLED"
39+
target_capacity = 123
40+
minimum_scaling_step_size = 123
41+
maximum_scaling_step_size = 123
42+
}
43+
44+
alb_name = "your-alb-name"
45+
target_group_name = "your-alb-target-group-name"
46+
target_group_protocol = "HTTP"
47+
target_group_health_check = {
48+
path = "/path/to/health/check"
49+
}
50+
listener_port = 123
51+
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
52+
security_group_alb = "your-alb-sg-name"
53+
54+
s3_bucket_force_destroy = true
55+
56+
base_domain = "example.com"
57+
domain_name = "your-service.example.com"
58+
```
859

960
## Usage
1061

examples/complete/main.tf

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
################################################################################
2-
# Locals
3-
################################################################################
1+
provider "aws" {
2+
region = "ap-south-1"
3+
}
44

55
locals {
66
task_definition_network_mode = "awsvpc"
@@ -12,6 +12,7 @@ locals {
1212

1313
alb_internal = false
1414

15+
target_group_key_name = "default-nginx"
1516
target_group_target_type = "ip"
1617

1718
listener_default_action_type = "forward"
@@ -40,7 +41,7 @@ module "ecs_deployment" {
4041

4142
load_balancer = [
4243
{
43-
target_group = "target_group"
44+
target_group = local.target_group_key_name
4445
container_name = var.container_name
4546
container_port = var.container_port
4647
}
@@ -70,8 +71,9 @@ module "ecs_deployment" {
7071
capacity_provider_default_auto_scaling_group_arn = var.asg_arn
7172
capacity_providers = {
7273
capacity_provider = {
73-
name = var.capacity_provider_name
74-
managed_scaling = var.capacity_provider_managed_scaling
74+
name = var.capacity_provider_name
75+
managed_termination_protection = "DISABLED"
76+
managed_scaling = var.capacity_provider_managed_scaling
7577
}
7678
}
7779
default_capacity_providers_strategies = [
@@ -100,7 +102,7 @@ module "ecs_deployment" {
100102
subnets_ids = var.public_subnets
101103

102104
target_groups = {
103-
target_group = {
105+
(local.target_group_key_name) = {
104106
name = var.target_group_name
105107
port = var.container_port
106108
protocol = var.target_group_protocol
@@ -111,7 +113,7 @@ module "ecs_deployment" {
111113
}
112114

113115
listeners = {
114-
listener = {
116+
this = {
115117
port = var.listener_port
116118
protocol = "HTTPS"
117119
certificate = "base_domain"
@@ -120,20 +122,23 @@ module "ecs_deployment" {
120122
default_action = [
121123
{
122124
type = local.listener_default_action_type
123-
target_group = var.target_group_name
125+
target_group = local.target_group_key_name
124126
}
125127
]
126128
}
127129
}
128130
}
131+
132+
# S3 Bucket
133+
s3_bucket_force_destroy = var.s3_bucket_force_destroy
129134
}
130135

131136
################################################################################
132137
# ACM
133138
################################################################################
134139

135140
data "aws_route53_zone" "base_domain" {
136-
name = var.domain_name
141+
name = var.base_domain
137142
}
138143

139144
################################################################################

examples/complete/outputs.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ output "alb_arn" {
4242

4343
output "target_group_id" {
4444
description = "Identifier of the Target Group instances"
45-
value = module.ecs_deployment.alb_target_groups_ids["this"]
45+
value = module.ecs_deployment.alb_target_groups_ids[local.target_group_key_name]
4646
}
4747

4848
output "target_group_arn" {
4949
description = "ARN of the Target Group instances"
50-
value = module.ecs_deployment.alb_target_groups_arns["this"]
50+
value = module.ecs_deployment.alb_target_groups_arns[local.target_group_key_name]
5151
}
5252

5353
output "listener_id" {

examples/complete/variables.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,16 @@ variable "security_group_alb" {
118118
type = string
119119
}
120120

121+
variable "s3_bucket_force_destroy" {
122+
description = "(Optional, Default:false) Boolean that indicates all objects (including any locked objects) should be deleted from the bucket when the bucket is destroyed so that the bucket can be destroyed without error."
123+
type = bool
124+
}
125+
126+
variable "base_domain" {
127+
description = "Base domain for ACM"
128+
type = string
129+
}
130+
121131
variable "domain_name" {
122132
description = "Domain name for ACM"
123133
type = string

main.tf

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
locals {
22
# ALB
3+
alb_access_logs_default_s3_configuration = var.create_s3_bucket_for_alb_logging ? {
4+
bucket = module.s3_bucket[0].bucket_id
5+
enabled = true
6+
prefix = var.s3_bucket_access_logs_prefix
7+
} : null
8+
alb_connection_logs_default_s3_configuration = var.create_s3_bucket_for_alb_logging ? {
9+
bucket = module.s3_bucket[0].bucket_id
10+
enabled = true
11+
prefix = var.s3_bucket_connection_logs_prefix
12+
} : null
313
alb_target_groups = {
414
for k, v in try(var.load_balancer.target_groups, {}) :
515
k => merge(
@@ -249,6 +259,9 @@ module "alb" {
249259
preserve_host_header = try(var.load_balancer.preserve_host_header, null)
250260
enable_deletion_protection = try(var.load_balancer.enable_deletion_protection, null)
251261

262+
access_logs = var.load_balancer.access_logs != null ? var.load_balancer.access_logs : local.alb_access_logs_default_s3_configuration
263+
connection_logs = var.load_balancer.connection_logs != null ? var.load_balancer.connection_logs : local.alb_connection_logs_default_s3_configuration
264+
252265
target_groups = local.alb_target_groups
253266

254267
listeners = local.alb_listeners
@@ -260,6 +273,88 @@ module "alb" {
260273
depends_on = [module.acm]
261274
}
262275

276+
################################################################################
277+
# S3 Bucket Sub-module
278+
################################################################################
279+
280+
data "aws_elb_service_account" "this" {}
281+
282+
module "s3_bucket" {
283+
source = "./modules/s3-bucket"
284+
285+
count = var.create_s3_bucket_for_alb_logging ? 1 : 0
286+
287+
bucket = var.s3_bucket_name
288+
bucket_force_destroy = var.s3_bucket_force_destroy
289+
290+
bucket_policies = {
291+
alb-logs = {
292+
id = "${var.s3_bucket_policy_id_prefix}-logs"
293+
294+
statements = [
295+
{
296+
sid = "AllowAccessToS3Bucket"
297+
298+
effect = "Allow"
299+
resources = [
300+
"${module.s3_bucket[0].bucket_arn}/*",
301+
]
302+
actions = [
303+
"s3:PutObject",
304+
]
305+
306+
principals = [
307+
{
308+
identifiers = [
309+
data.aws_elb_service_account.this.arn
310+
]
311+
type = "AWS"
312+
}
313+
]
314+
},
315+
{
316+
sid = "AllowPutObjectToS3Bucket"
317+
318+
effect = "Allow"
319+
resources = [
320+
"${module.s3_bucket[0].bucket_arn}/*"
321+
]
322+
actions = [
323+
"s3:PutObject"
324+
]
325+
326+
principals = [
327+
{
328+
identifiers = ["delivery.logs.amazonaws.com"]
329+
type = "Service"
330+
}
331+
]
332+
},
333+
{
334+
sid = "AllowGetBucketAclFromS3Bucket"
335+
336+
effect = "Allow"
337+
resources = [
338+
module.s3_bucket[0].bucket_arn
339+
]
340+
actions = [
341+
"s3:GetBucketAcl"
342+
]
343+
344+
principals = [
345+
{
346+
identifiers = ["delivery.logs.amazonaws.com"]
347+
type = "Service"
348+
}
349+
]
350+
}
351+
]
352+
}
353+
}
354+
355+
tags = var.s3_bucket_tags
356+
}
357+
263358
################################################################################
264359
# Amazon Certificates Manager Sub-module
265360
################################################################################

modules/alb/.header.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
This sub-module creates:
44

5-
1. Application Load Balancer in the given subnets
5+
1. Application Load Balancer in the given subnets with logging configuration
66
2. Target Groups with Health Check configuration
77
3. Listeners with Default Action configuration, and
88
4. Listener Rules with Actions with `forward` and `authenticate-oidc` types, and Conditions involving `host_header`, `path_pattern`, and `http_request_method`.

outputs.tf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,20 @@ output "alb_listener_rules_arns" {
8989
value = try(module.alb[0].listener_rules_arns, null)
9090
}
9191

92+
################################################################################
93+
# S3 Bucket
94+
################################################################################
95+
96+
output "s3_bucket_id" {
97+
description = "Name of the bucket."
98+
value = try(module.s3_bucket[0].bucket_id, null)
99+
}
100+
101+
output "s3_bucket_arn" {
102+
description = "ARN of the bucket."
103+
value = try(module.s3_bucket[0].bucket_arn, null)
104+
}
105+
92106
################################################################################
93107
# Capacity Provider
94108
################################################################################

variables.tf

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ variable "load_balancer" {
109109
security_groups_ids = optional(list(string), [])
110110
preserve_host_header = optional(bool)
111111
enable_deletion_protection = optional(bool, false)
112+
access_logs = optional(any, null)
113+
connection_logs = optional(any, null)
112114
target_groups = optional(any, {})
113115
listeners = optional(any, {})
114116
listener_rules = optional(any, {})
@@ -117,6 +119,58 @@ variable "load_balancer" {
117119
default = {}
118120
}
119121

122+
################################################################################
123+
# S3 Bucket
124+
################################################################################
125+
126+
variable "create_s3_bucket_for_alb_logging" {
127+
description = "(Optional) Creates S3 bucket for storing ALB Access and Connection Logs."
128+
type = bool
129+
nullable = false
130+
default = true
131+
}
132+
133+
variable "s3_bucket_name" {
134+
description = "(Optional, Forces new resource) Name of the bucket."
135+
type = string
136+
default = null
137+
}
138+
139+
variable "s3_bucket_force_destroy" {
140+
description = "(Optional, Default:false) Boolean that indicates all objects (including any locked objects) should be deleted from the bucket when the bucket is destroyed so that the bucket can be destroyed without error."
141+
type = bool
142+
nullable = false
143+
default = false
144+
}
145+
146+
variable "s3_bucket_policy_id_prefix" {
147+
description = "(Optional) - Prefix of the ID for the policy document."
148+
type = string
149+
nullable = false
150+
default = "ecs-deployment-alb-"
151+
}
152+
153+
variable "s3_bucket_access_logs_prefix" {
154+
description = "(Optional) - Prefix for storing ALB access logs in the S3 bucket."
155+
type = string
156+
nullable = false
157+
default = "alb-access-logs"
158+
}
159+
160+
variable "s3_bucket_connection_logs_prefix" {
161+
description = "(Optional) - Prefix for storing ALB connection logs in the S3 bucket."
162+
type = string
163+
nullable = false
164+
default = "alb-connection-logs"
165+
}
166+
167+
variable "s3_bucket_tags" {
168+
description = "(Optional) Map of tags to assign to the bucket."
169+
type = map(string)
170+
nullable = false
171+
default = {}
172+
}
173+
120174
################################################################################
121175
# Amazon Certificates Manager Sub-module
122176
################################################################################

0 commit comments

Comments
 (0)