Skip to content

Commit 8111b81

Browse files
Enable creation of S3 bucket for Flow Logs
1 parent ac12964 commit 8111b81

File tree

7 files changed

+191
-11
lines changed

7 files changed

+191
-11
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ Sometimes it is handy to have public access to Redshift clusters (for example if
195195
This module is able to provision the collection of VPC Flow Logs by setting `enable_flow_log = true`.
196196
The [default behaviour](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/complete-vpc) will push the Flow Logs to a CloudWatch log group that gets created together the required IAM role.
197197
Through the module's arguments it is possible to pass in an existing [CloudWatch log group](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/vpc-flow-provided-cloudwatch-log-group) and/or an existing [IAM role](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/vpc-flow-provided-cloudwatch-role) to be used instead of creating these resources.
198-
It is also possible to pass in a [S3 bucket](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/vpc-flow-provided-s3-bucket) as the destination for the logs, instead of a CloudWatch log group.
198+
It is also possible to push FLow Logs to S3.
199+
To that end the module allows for a [S3 bucket](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/vpc-flow-provided-s3-bucket) to be proivided as the destination for the logs, or to [have it created by the module](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/vpc-flow-create-s3-bucket).
199200

200201
## Examples
201202

@@ -206,6 +207,7 @@ It is also possible to pass in a [S3 bucket](https://github.com/terraform-aws-mo
206207
* [Flow Log CloudWatch log group provided](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/vpc-flow-provided-cloudwatch-log-group)
207208
* [Flow Log IAM role for CloudWatch provided](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/vpc-flow-provided-cloudwatch-role)
208209
* [Flow Log S3 bucket provided](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/vpc-flow-provided-s3-bucket)
210+
* [Flow Log create S3 bucket](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/vpc-flow-create-s3-bucket)
209211
* Few tests and edge cases examples: [#46](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/issue-46-no-private-subnets), [#44](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/issue-44-asymmetric-private-subnets), [#108](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/issue-108-route-already-exists)
210212

211213
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# VPC Flow Logs pushed to new S3 bucket
2+
3+
Configuration in this directory creates set of VPC resources with FLow Logs enabled and configured to push to a new S3 bucket.
4+
5+
## Usage
6+
7+
To run this example you need to execute:
8+
9+
```bash
10+
$ terraform init
11+
$ terraform plan
12+
$ terraform apply
13+
```
14+
15+
Note that this example may create resources which can cost money (AWS Elastic IP, for example). Run `terraform destroy` when you don't need these resources.
16+
17+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
18+
## Outputs
19+
20+
| Name | Description |
21+
|------|-------------|
22+
| azs | A list of availability zones spefified as argument to this module |
23+
| nat\_public\_ips | List of public Elastic IPs created for AWS NAT Gateway |
24+
| private\_subnets | List of IDs of private subnets |
25+
| public\_subnets | List of IDs of public subnets |
26+
| vpc\_cidr\_block | The CIDR block of the VPC |
27+
| vpc\_id | The ID of the VPC |
28+
29+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
provider "aws" {
2+
region = "eu-west-1"
3+
}
4+
5+
data "aws_security_group" "default" {
6+
name = "default"
7+
vpc_id = module.vpc.vpc_id
8+
}
9+
10+
module "vpc" {
11+
source = "../../"
12+
13+
name = "flow-log-provided-s3-bucket"
14+
15+
cidr = "10.0.0.0/16"
16+
17+
azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
18+
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
19+
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
20+
21+
assign_generated_ipv6_cidr_block = true
22+
23+
enable_nat_gateway = true
24+
single_nat_gateway = true
25+
26+
enable_flow_log = true
27+
create_flow_log_cloudwatch_log_group = false
28+
create_flow_log_cloudwatch_iam_role = false
29+
create_flow_log_s3_bucket = true
30+
push_flow_log_to_s3 = true
31+
flow_log_force_destroy_s3_bucket = true
32+
33+
tags = {
34+
Owner = "user"
35+
Environment = "dev"
36+
}
37+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# VPC
2+
output "vpc_id" {
3+
description = "The ID of the VPC"
4+
value = module.vpc.vpc_id
5+
}
6+
7+
# CIDR blocks
8+
output "vpc_cidr_block" {
9+
description = "The CIDR block of the VPC"
10+
value = module.vpc.vpc_cidr_block
11+
}
12+
13+
//output "vpc_ipv6_cidr_block" {
14+
// description = "The IPv6 CIDR block"
15+
// value = ["${module.vpc.vpc_ipv6_cidr_block}"]
16+
//}
17+
18+
# Subnets
19+
output "private_subnets" {
20+
description = "List of IDs of private subnets"
21+
value = module.vpc.private_subnets
22+
}
23+
24+
output "public_subnets" {
25+
description = "List of IDs of public subnets"
26+
value = module.vpc.public_subnets
27+
}
28+
29+
# NAT gateways
30+
output "nat_public_ips" {
31+
description = "List of public Elastic IPs created for AWS NAT Gateway"
32+
value = module.vpc.nat_public_ips
33+
}
34+
35+
# AZs
36+
output "azs" {
37+
description = "A list of availability zones spefified as argument to this module"
38+
value = module.vpc.azs
39+
}
40+

examples/vpc-flow-provided-s3-bucket/main.tf

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ module "vpc" {
2323
enable_nat_gateway = true
2424
single_nat_gateway = true
2525

26-
enable_flow_log = true
26+
enable_flow_log = true
2727
create_flow_log_cloudwatch_log_group = false
28-
create_flow_log_cloudwatch_iam_role = false
29-
flow_log_destination_type = "s3"
30-
flow_log_destination_arn = aws_s3_bucket.vpf_flow_log.arn
28+
create_flow_log_cloudwatch_iam_role = false
29+
push_flow_log_to_s3 = true
30+
flow_log_destination_arn = aws_s3_bucket.vpf_flow_log.arn
3131

3232
tags = {
3333
Owner = "user"
@@ -38,6 +38,8 @@ module "vpc" {
3838
resource "aws_s3_bucket" "vpf_flow_log" {
3939
bucket = "aws-vpc-module-test-flow-logs"
4040
policy = data.aws_iam_policy_document.flow_log_s3.json
41+
42+
force_destroy = true
4143
}
4244

4345
data "aws_iam_policy_document" "flow_log_s3" {

flow-logs.tf

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,16 @@ locals {
44

55
create_flow_log_cloudwatch_iam_role = local.enable_flow_log && var.create_flow_log_cloudwatch_iam_role
66
create_flow_log_cloudwatch_log_group = local.enable_flow_log && var.create_flow_log_cloudwatch_log_group
7+
create_flow_log_s3_bucket = local.enable_flow_log && var.create_flow_log_s3_bucket
8+
9+
flow_log_cloudwatch_destination = local.create_flow_log_cloudwatch_log_group ? join("", aws_cloudwatch_log_group.flow_log.*.arn) : var.flow_log_destination_arn
10+
flow_log_s3_destination = local.create_flow_log_s3_bucket ? join("", aws_s3_bucket.flow_log.*.arn) : var.flow_log_destination_arn
711

812
flow_log_iam_role_arn = local.create_flow_log_cloudwatch_iam_role ? join("", aws_iam_role.vpc_flow_log_cloudwatch.*.arn) : var.flow_log_cloudwatch_iam_role_arn
9-
flow_log_destination = local.create_flow_log_cloudwatch_log_group ? join("", aws_cloudwatch_log_group.flow_log.*.arn) : var.flow_log_destination_arn
13+
14+
flow_log_destination = var.push_flow_log_to_s3 ? local.flow_log_s3_destination : local.flow_log_cloudwatch_destination
15+
16+
flow_log_destination_type = var.push_flow_log_to_s3 ? "s3" : "cloud-watch-logs"
1017
}
1118

1219
###################
@@ -15,7 +22,7 @@ locals {
1522
resource "aws_flow_log" "this" {
1623
count = local.enable_flow_log ? 1 : 0
1724

18-
log_destination_type = var.flow_log_destination_type
25+
log_destination_type = local.flow_log_destination_type
1926
log_destination = local.flow_log_destination
2027
iam_role_arn = local.flow_log_iam_role_arn
2128
vpc_id = local.vpc_id
@@ -94,3 +101,56 @@ data "aws_iam_policy_document" "flow_log_cloudwatch" {
94101
resources = ["*"]
95102
}
96103
}
104+
105+
#############
106+
# Flow Log S3
107+
#############
108+
resource "aws_s3_bucket" "flow_log" {
109+
count = local.create_flow_log_s3_bucket ? 1 : 0
110+
111+
bucket = "flow-log-${local.vpc_id}"
112+
policy = join("", data.aws_iam_policy_document.flow_log_s3.*.json)
113+
114+
force_destroy = var.flow_log_force_destroy_s3_bucket
115+
116+
tags = merge(var.tags, var.vpc_flow_log_tags)
117+
}
118+
119+
data "aws_iam_policy_document" "flow_log_s3" {
120+
count = local.create_flow_log_s3_bucket ? 1 : 0
121+
122+
statement {
123+
sid = "AWSLogDeliveryWrite"
124+
125+
principals {
126+
type = "Service"
127+
identifiers = ["delivery.logs.amazonaws.com"]
128+
}
129+
130+
effect = "Allow"
131+
132+
actions = [
133+
"s3:PutObject",
134+
]
135+
136+
resources = [
137+
"arn:aws:s3:::flow-log-${local.vpc_id}/*"]
138+
}
139+
140+
statement {
141+
sid = "AWSLogDeliveryAclCheck"
142+
143+
principals {
144+
type = "Service"
145+
identifiers = ["delivery.logs.amazonaws.com"]
146+
}
147+
148+
effect = "Allow"
149+
150+
actions = [
151+
"s3:GetBucketAcl",
152+
]
153+
154+
resources = ["arn:aws:s3:::flow-log-${local.vpc_id}"]
155+
}
156+
}

variables.tf

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,10 +1402,10 @@ variable "flow_log_traffic_type" {
14021402
default = "ALL"
14031403
}
14041404

1405-
variable "flow_log_destination_type" {
1406-
description = "The type of the logging destination. Valid values: cloud-watch-logs, s3."
1407-
type = string
1408-
default = "cloud-watch-logs"
1405+
variable "push_flow_log_to_s3" {
1406+
description = "Whether or not to change the default behaviour from pushing logs to CloudWatch to pushing to S3"
1407+
type = bool
1408+
default = false
14091409
}
14101410

14111411
variable "flow_log_destination_arn" {
@@ -1432,4 +1432,14 @@ variable "flow_log_cloudwatch_iam_role_arn" {
14321432
default = ""
14331433
}
14341434

1435+
variable "create_flow_log_s3_bucket" {
1436+
description = "Whether or not to create an S3 bucket to push the VPC Flow Logs to"
1437+
type = bool
1438+
default = false
1439+
}
14351440

1441+
variable "flow_log_force_destroy_s3_bucket" {
1442+
description = "Whether or not to force destroy the Flow Logs S3 bucket created by this module"
1443+
type = bool
1444+
default = false
1445+
}

0 commit comments

Comments
 (0)