Skip to content

Commit c60216f

Browse files
authored
Merge pull request #83 from aws-ia/f-s3vpcflowlogs
add s3 option for vpc flow logs
2 parents b3b208a + f944cde commit c60216f

File tree

13 files changed

+150
-24
lines changed

13 files changed

+150
-24
lines changed

defaults.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ locals {
1212

1313
# sensiblie defaults that can all be overridden
1414
log_destination_type = var.vpc_flow_logs.log_destination_type == null ? "cloud-watch-logs" : var.vpc_flow_logs.log_destination_type
15-
retention_in_days = var.vpc_flow_logs.retention_in_days == null ? 180 : var.vpc_flow_logs.retention_in_days
15+
retention_in_days = try(var.vpc_flow_logs.retention_in_days, null)
1616
traffic_type = var.vpc_flow_logs.traffic_type == null ? "ALL" : var.vpc_flow_logs.traffic_type
17-
destination_options = var.vpc_flow_logs.destination_options == null ? {
17+
destination_options = can(var.vpc_flow_logs.destination_options) ? {
1818
file_format = "plain-text"
1919
hive_compatible_partitions = false
2020
per_hour_partition = false

examples/public_private_flow_logs/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ At this point, only cloud-watch logs are support, pending: https://github.com/aw
77

88
## Requirements
99

10-
No requirements.
10+
| Name | Version |
11+
|------|---------|
12+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.15.0 |
13+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.73.0 |
1114

1215
## Providers
1316

1417
| Name | Version |
1518
|------|---------|
16-
| <a name="provider_aws"></a> [aws](#provider\_aws) | n/a |
19+
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.73.0 |
1720

1821
## Modules
1922

@@ -32,6 +35,7 @@ No requirements.
3235
| Name | Description | Type | Default | Required |
3336
|------|-------------|------|---------|:--------:|
3437
| <a name="input_kms_key_id"></a> [kms\_key\_id](#input\_kms\_key\_id) | KMS Key ID | `string` | `null` | no |
38+
| <a name="input_vpc_flow_logs"></a> [vpc\_flow\_logs](#input\_vpc\_flow\_logs) | Whether or not to create VPC flow logs and which type. Options: "cloudwatch", "s3", "none". | <pre>object({<br> log_destination = optional(string)<br> iam_role_arn = optional(string)<br> kms_key_id = optional(string)<br><br> log_destination_type = string<br> retention_in_days = optional(number)<br> tags = optional(map(string))<br> traffic_type = optional(string)<br> destination_options = optional(object({<br> file_format = optional(string)<br> hive_compatible_partitions = optional(bool)<br> per_hour_partition = optional(bool)<br> }))<br> })</pre> | <pre>{<br> "kms_key_id": null,<br> "log_destination_type": "cloud-watch-logs",<br> "retention_in_days": 180<br>}</pre> | no |
3539

3640
## Outputs
3741

examples/public_private_flow_logs/main.tf

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module "vpc" {
44
source = "aws-ia/vpc/aws"
55
version = ">= 2.0.0"
66

7-
name = "tag-test"
7+
name = "public-private-flowlogs"
88
cidr_block = "10.0.0.0/20"
99
az_count = 2
1010

@@ -26,11 +26,7 @@ module "vpc" {
2626
}
2727
}
2828

29-
vpc_flow_logs = {
30-
log_destination_type = "cloud-watch-logs"
31-
retention_in_days = 180
32-
kms_key_id = var.kms_key_id
33-
}
29+
vpc_flow_logs = var.vpc_flow_logs
3430

3531
tags = {
3632
"key" = "value"

examples/public_private_flow_logs/outputs.tf

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ output "public_subnets" {
33
value = module.vpc.public_subnet_attributes_by_az
44
}
55

6+
output "private_subnets" {
7+
description = "Map of private subnet attributes grouped by az."
8+
value = module.vpc.private_subnet_attributes_by_az
9+
}
10+
11+
## Used for Testing, do not delete
12+
613
output "public_subnets_tags_length" {
714
description = "Count of public subnet tags for a single az."
815
value = length(module.vpc.public_subnet_attributes_by_az[data.aws_availability_zones.current.names[0]].tags)
@@ -12,8 +19,3 @@ output "private_subnets_tags_length" {
1219
description = "Count of private subnet tags for a single az."
1320
value = length(module.vpc.private_subnet_attributes_by_az["private/${data.aws_availability_zones.current.names[0]}"].tags)
1421
}
15-
16-
output "private_subnets" {
17-
description = "Map of private subnet attributes grouped by az."
18-
value = module.vpc.private_subnet_attributes_by_az
19-
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
terraform {
2+
required_version = ">= 0.15.0"
3+
experiments = [module_variable_optional_attrs]
4+
required_providers {
5+
aws = {
6+
source = "hashicorp/aws"
7+
version = ">= 3.73.0"
8+
}
9+
}
10+
}

examples/public_private_flow_logs/variables.tf

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,28 @@ variable "kms_key_id" {
33
type = string
44
default = null
55
}
6+
7+
variable "vpc_flow_logs" {
8+
description = "Whether or not to create VPC flow logs and which type. Options: \"cloudwatch\", \"s3\", \"none\"."
9+
10+
type = object({
11+
log_destination = optional(string)
12+
iam_role_arn = optional(string)
13+
kms_key_id = optional(string)
14+
15+
log_destination_type = string
16+
retention_in_days = optional(number)
17+
tags = optional(map(string))
18+
traffic_type = optional(string)
19+
destination_options = optional(object({
20+
file_format = optional(string)
21+
hive_compatible_partitions = optional(bool)
22+
per_hour_partition = optional(bool)
23+
}))
24+
})
25+
default = {
26+
log_destination_type = "cloud-watch-logs"
27+
retention_in_days = 180
28+
kms_key_id = null
29+
}
30+
}

examples/transit_gateway/outputs.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
## Used for Testing, do not delete
2+
13
output "tgw_subnets_tags_length" {
24
description = "Count of tgw subnet tags for a single az."
35
value = length(module.vpc.tgw_subnet_attributes_by_az[data.aws_availability_zones.current.names[0]].tags)

modules/flow_logs/main.tf

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ locals {
44

55
# which log destination to use
66
log_destination = local.create_flow_log_destination ? (
7-
var.flow_log_defintion.log_destination_type == "cloud-watch-logs" ? module.cloudwatch_log_group[0].log_group.arn : null # change to s3 when implemented
7+
var.flow_log_defintion.log_destination_type == "cloud-watch-logs" ? module.cloudwatch_log_group[0].log_group.arn : module.s3_log_bucket[0].bucket_flow_logs_attributes.arn # change to s3 when implemented
88
) : var.flow_log_defintion.log_destination
99

1010
# Use IAM from submodule if if not passed
1111
iam_role_arn = local.create_flow_log_destination ? (
12-
var.flow_log_defintion.log_destination_type == "cloud-watch-logs" ? module.cloudwatch_log_group[0].iam_role.arn : null # change to s3 when implemented
12+
var.flow_log_defintion.log_destination_type == "cloud-watch-logs" ? module.cloudwatch_log_group[0].iam_role.arn : null # s3: unnecessary, svc creates its own bucket policy
1313
) : var.flow_log_defintion.iam_role_arn
1414
}
1515

@@ -20,12 +20,20 @@ module "cloudwatch_log_group" {
2020
version = "1.0.0"
2121

2222
name = var.name
23-
retention_in_days = var.flow_log_defintion.retention_in_days
23+
retention_in_days = var.flow_log_defintion.retention_in_days == null ? 180 : var.flow_log_defintion.retention_in_days
2424
kms_key_id = var.flow_log_defintion.kms_key_id
2525
aws_service_principal = "vpc-flow-logs.amazonaws.com"
2626
tags = var.tags
2727
}
2828

29+
module "s3_log_bucket" {
30+
# if create destination and type = s3
31+
count = (local.create_flow_log_destination && var.flow_log_defintion.log_destination_type == "s3") ? 1 : 0
32+
source = "./modules/s3_log_bucket"
33+
34+
name = var.name
35+
}
36+
2937
resource "aws_flow_log" "main" {
3038
log_destination = local.log_destination
3139
iam_role_arn = local.iam_role_arn
@@ -34,12 +42,12 @@ resource "aws_flow_log" "main" {
3442
vpc_id = var.vpc_id
3543

3644
dynamic "destination_options" {
37-
for_each = var.flow_log_defintion.log_destination_type == "s3" ? var.flow_log_defintion.destination_options : {}
45+
for_each = var.flow_log_defintion.log_destination_type == "s3" ? [true] : []
3846

3947
content {
40-
file_format = each.value.file_format
41-
per_hour_partition = each.value.per_hour_partition
42-
hive_compatible_partitions = each.value.hive_compatible_partitions
48+
file_format = var.flow_log_defintion.destination_options.file_format
49+
per_hour_partition = var.flow_log_defintion.destination_options.per_hour_partition
50+
hive_compatible_partitions = var.flow_log_defintion.destination_options.hive_compatible_partitions
4351
}
4452
}
4553

@@ -48,4 +56,3 @@ resource "aws_flow_log" "main" {
4856
var.tags
4957
)
5058
}
51-
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#tfsec:ignore:aws-s3-encryption-customer-key tfsec:ignore:aws-s3-enable-bucket-logging tfsec:ignore:aws-s3-enable-versioning
2+
resource "aws_s3_bucket" "flow_logs" {
3+
bucket_prefix = "vpc-flow-logs-${var.name}"
4+
force_destroy = true
5+
}
6+
7+
resource "aws_s3_bucket_public_access_block" "flow_logs" {
8+
bucket = aws_s3_bucket.flow_logs.bucket
9+
10+
block_public_acls = true
11+
block_public_policy = true
12+
ignore_public_acls = true
13+
restrict_public_buckets = true
14+
}
15+
16+
#tfsec:ignore:aws-s3-encryption-customer-key
17+
resource "aws_s3_bucket_server_side_encryption_configuration" "flow_logs" {
18+
bucket = aws_s3_bucket.flow_logs.bucket
19+
20+
rule {
21+
apply_server_side_encryption_by_default {
22+
sse_algorithm = "AES256"
23+
}
24+
}
25+
}
26+
27+
resource "aws_s3_bucket_lifecycle_configuration" "flow_logs" {
28+
bucket = aws_s3_bucket.flow_logs.bucket
29+
30+
rule {
31+
id = "transition"
32+
33+
transition {
34+
days = 30
35+
storage_class = "STANDARD_IA"
36+
}
37+
38+
expiration {
39+
days = 60
40+
}
41+
42+
status = "Enabled"
43+
}
44+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
output "bucket_flow_logs_attributes" {
2+
value = aws_s3_bucket.flow_logs
3+
}

0 commit comments

Comments
 (0)