Skip to content

Commit f2f8e4a

Browse files
author
nozaq
committed
feat: allow using an external bucket instead of creating a new one
fixes nozaq#47
1 parent d3aa314 commit f2f8e4a

17 files changed

+405
-126
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ Check [the example](./examples/root-example/regions.tf) to understand how these
7777
Note that you need to define a provider for each AWS region and pass them to the module. Currently this is the recommended way to handle multiple regions in one module.
7878
Detailed information can be found at [Providers within Modules - Terraform Docs].
7979

80+
A new S3 bucket to store audit logs is automatically created by default, while the external S3 bucket can be specified. It is useful when you already have a centralized S3 bucket to store all logs. Please see [external-bucket](./examples/external-bucket) example for more detail.
81+
8082
## Submodules
8183

8284
This module is composed of several submodules and each of which can be used independently.
@@ -128,6 +130,7 @@ This module is composed of several submodules and each of which can be used inde
128130
| support\_iam\_role\_name | The name of the the support role. | string | `"IAM-Support"` | no |
129131
| support\_iam\_role\_policy\_name | The name of the support role policy. | string | `"IAM-Support-Role"` | no |
130132
| support\_iam\_role\_principal\_arn | The ARN of the IAM principal element by which the support role could be assumed. | string | n/a | yes |
133+
| use\_external\_audit\_log\_bucket | A boolean that indicates whether the specific audit log bucket already exists. Create a new S3 bucket if it is set to false. | string | `"false"` | no |
131134
| vpc\_iam\_role\_name | The name of the IAM Role which VPC Flow Logs will use. | string | `"VPC-Flow-Logs-Publisher"` | no |
132135
| vpc\_iam\_role\_policy\_name | The name of the IAM Role Policy which VPC Flow Logs will use. | string | `"VPC-Flow-Logs-Publish-Policy"` | no |
133136
| vpc\_log\_group\_name | The name of CloudWatch Logs group to which VPC Flow Logs are delivered. | string | `"default-vpc-flow-logs"` | no |

bucket.tf

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# --------------------------------------------------------------------------------------------------
2+
# Configure the S3 bucket to store audit logs.
3+
# --------------------------------------------------------------------------------------------------
4+
locals {
5+
use_external_bucket = var.use_external_audit_log_bucket
6+
audit_log_bucket_id = local.use_external_bucket ? data.aws_s3_bucket.external[0].id : module.audit_log_bucket.this_bucket.id
7+
audit_log_bucket_arn = local.use_external_bucket ? data.aws_s3_bucket.external[0].arn : module.audit_log_bucket.this_bucket.arn
8+
}
9+
10+
# --------------------------------------------------------------------------------------------------
11+
# Case 1. Use the external S3 bucket.
12+
# --------------------------------------------------------------------------------------------------
13+
data "aws_s3_bucket" "external" {
14+
count = local.use_external_bucket ? 1 : 0
15+
bucket = var.audit_log_bucket_name
16+
}
17+
18+
# --------------------------------------------------------------------------------------------------
19+
# Case 2. Create a new S3 bucket.
20+
#
21+
# Create a S3 bucket to store various audit logs.
22+
# Bucket policies are derived from the default bucket policy described in
23+
# AWS Config Developer Guide and AWS CloudTrail User Guide.
24+
# https://docs.aws.amazon.com/config/latest/developerguide/s3-bucket-policy.html
25+
# https://docs.aws.amazon.com/awscloudtrail/latest/userguide/create-s3-bucket-policy-for-cloudtrail.html
26+
# --------------------------------------------------------------------------------------------------
27+
module "audit_log_bucket" {
28+
source = "./modules/secure-bucket"
29+
30+
bucket_name = var.audit_log_bucket_name
31+
log_bucket_name = "${var.audit_log_bucket_name}-access-logs"
32+
lifecycle_glacier_transition_days = var.audit_log_lifecycle_glacier_transition_days
33+
force_destroy = var.audit_log_bucket_force_destroy
34+
enabled = ! local.use_external_bucket
35+
}
36+
37+
resource "aws_s3_bucket_policy" "audit_log" {
38+
count = local.use_external_bucket ? 0 : 1
39+
40+
bucket = module.audit_log_bucket.this_bucket.id
41+
policy = <<END_OF_POLICY
42+
{
43+
"Version": "2012-10-17",
44+
"Statement": [
45+
{
46+
"Sid": "AWSCloudTrailAclCheckForConfig",
47+
"Effect": "Allow",
48+
"Principal": {"Service": "config.amazonaws.com"},
49+
"Action": "s3:GetBucketAcl",
50+
"Resource": "${module.audit_log_bucket.this_bucket.arn}"
51+
},
52+
{
53+
"Sid": " AWSCloudTrailWriteForConfig",
54+
"Effect": "Allow",
55+
"Principal": {"Service": "config.amazonaws.com"},
56+
"Action": "s3:PutObject",
57+
"Resource": "${module.audit_log_bucket.this_bucket.arn}/config/AWSLogs/${var.aws_account_id}/Config/*",
58+
"Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}}
59+
},
60+
{
61+
"Sid": "AWSCloudTrailAclCheckForCloudTrail",
62+
"Effect": "Allow",
63+
"Principal": {
64+
"Service": "cloudtrail.amazonaws.com"
65+
},
66+
"Action": "s3:GetBucketAcl",
67+
"Resource": "${module.audit_log_bucket.this_bucket.arn}"
68+
},
69+
{
70+
"Sid": "AWSCloudTrailWriteForCloudTrail",
71+
"Effect": "Allow",
72+
"Principal": {
73+
"Service": "cloudtrail.amazonaws.com"
74+
},
75+
"Action": "s3:PutObject",
76+
"Resource": "${module.audit_log_bucket.this_bucket.arn}/cloudtrail/AWSLogs/${var.aws_account_id}/*",
77+
"Condition": {
78+
"StringEquals": {
79+
"s3:x-amz-acl": "bucket-owner-full-control"
80+
}
81+
}
82+
}
83+
]
84+
}
85+
END_OF_POLICY
86+
}

config_baselines.tf

+18-18
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ POLICY
2828
data "aws_iam_policy_document" "recoder_publish_policy" {
2929
statement {
3030
actions = ["s3:PutObject"]
31-
resources = ["${module.audit_log_bucket.this_bucket.arn}/config/AWSLogs/${var.aws_account_id}/*"]
31+
resources = ["${local.audit_log_bucket_arn}/config/AWSLogs/${var.aws_account_id}/*"]
3232

3333
condition {
3434
test = "StringLike"
@@ -39,7 +39,7 @@ data "aws_iam_policy_document" "recoder_publish_policy" {
3939

4040
statement {
4141
actions = ["s3:GetBucketAcl"]
42-
resources = [module.audit_log_bucket.this_bucket.arn]
42+
resources = [local.audit_log_bucket_arn]
4343
}
4444

4545
statement {
@@ -85,7 +85,7 @@ resource "aws_iam_role_policy_attachment" "recoder_read_policy" {
8585
module "config_baseline_ap-northeast-1" {
8686
source = "./modules/config-baseline"
8787
iam_role_arn = aws_iam_role.recorder.arn
88-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
88+
s3_bucket_name = local.audit_log_bucket_id
8989
s3_key_prefix = var.config_s3_bucket_key_prefix
9090
delivery_frequency = var.config_delivery_frequency
9191
sns_topic_name = var.config_sns_topic_name
@@ -98,7 +98,7 @@ module "config_baseline_ap-northeast-1" {
9898
module "config_baseline_ap-northeast-2" {
9999
source = "./modules/config-baseline"
100100
iam_role_arn = aws_iam_role.recorder.arn
101-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
101+
s3_bucket_name = local.audit_log_bucket_id
102102
s3_key_prefix = var.config_s3_bucket_key_prefix
103103
delivery_frequency = var.config_delivery_frequency
104104
sns_topic_name = var.config_sns_topic_name
@@ -111,7 +111,7 @@ module "config_baseline_ap-northeast-2" {
111111
module "config_baseline_ap-south-1" {
112112
source = "./modules/config-baseline"
113113
iam_role_arn = aws_iam_role.recorder.arn
114-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
114+
s3_bucket_name = local.audit_log_bucket_id
115115
s3_key_prefix = var.config_s3_bucket_key_prefix
116116
delivery_frequency = var.config_delivery_frequency
117117
sns_topic_name = var.config_sns_topic_name
@@ -124,7 +124,7 @@ module "config_baseline_ap-south-1" {
124124
module "config_baseline_ap-southeast-1" {
125125
source = "./modules/config-baseline"
126126
iam_role_arn = aws_iam_role.recorder.arn
127-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
127+
s3_bucket_name = local.audit_log_bucket_id
128128
s3_key_prefix = var.config_s3_bucket_key_prefix
129129
delivery_frequency = var.config_delivery_frequency
130130
sns_topic_name = var.config_sns_topic_name
@@ -137,7 +137,7 @@ module "config_baseline_ap-southeast-1" {
137137
module "config_baseline_ap-southeast-2" {
138138
source = "./modules/config-baseline"
139139
iam_role_arn = aws_iam_role.recorder.arn
140-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
140+
s3_bucket_name = local.audit_log_bucket_id
141141
s3_key_prefix = var.config_s3_bucket_key_prefix
142142
delivery_frequency = var.config_delivery_frequency
143143
sns_topic_name = var.config_sns_topic_name
@@ -150,7 +150,7 @@ module "config_baseline_ap-southeast-2" {
150150
module "config_baseline_ca-central-1" {
151151
source = "./modules/config-baseline"
152152
iam_role_arn = aws_iam_role.recorder.arn
153-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
153+
s3_bucket_name = local.audit_log_bucket_id
154154
s3_key_prefix = var.config_s3_bucket_key_prefix
155155
delivery_frequency = var.config_delivery_frequency
156156
sns_topic_name = var.config_sns_topic_name
@@ -163,7 +163,7 @@ module "config_baseline_ca-central-1" {
163163
module "config_baseline_eu-central-1" {
164164
source = "./modules/config-baseline"
165165
iam_role_arn = aws_iam_role.recorder.arn
166-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
166+
s3_bucket_name = local.audit_log_bucket_id
167167
s3_key_prefix = var.config_s3_bucket_key_prefix
168168
delivery_frequency = var.config_delivery_frequency
169169
sns_topic_name = var.config_sns_topic_name
@@ -176,7 +176,7 @@ module "config_baseline_eu-central-1" {
176176
module "config_baseline_eu-north-1" {
177177
source = "./modules/config-baseline"
178178
iam_role_arn = aws_iam_role.recorder.arn
179-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
179+
s3_bucket_name = local.audit_log_bucket_id
180180
s3_key_prefix = var.config_s3_bucket_key_prefix
181181
delivery_frequency = var.config_delivery_frequency
182182
sns_topic_name = var.config_sns_topic_name
@@ -189,7 +189,7 @@ module "config_baseline_eu-north-1" {
189189
module "config_baseline_eu-west-1" {
190190
source = "./modules/config-baseline"
191191
iam_role_arn = aws_iam_role.recorder.arn
192-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
192+
s3_bucket_name = local.audit_log_bucket_id
193193
s3_key_prefix = var.config_s3_bucket_key_prefix
194194
delivery_frequency = var.config_delivery_frequency
195195
sns_topic_name = var.config_sns_topic_name
@@ -202,7 +202,7 @@ module "config_baseline_eu-west-1" {
202202
module "config_baseline_eu-west-2" {
203203
source = "./modules/config-baseline"
204204
iam_role_arn = aws_iam_role.recorder.arn
205-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
205+
s3_bucket_name = local.audit_log_bucket_id
206206
s3_key_prefix = var.config_s3_bucket_key_prefix
207207
delivery_frequency = var.config_delivery_frequency
208208
sns_topic_name = var.config_sns_topic_name
@@ -215,7 +215,7 @@ module "config_baseline_eu-west-2" {
215215
module "config_baseline_eu-west-3" {
216216
source = "./modules/config-baseline"
217217
iam_role_arn = aws_iam_role.recorder.arn
218-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
218+
s3_bucket_name = local.audit_log_bucket_id
219219
s3_key_prefix = var.config_s3_bucket_key_prefix
220220
delivery_frequency = var.config_delivery_frequency
221221
sns_topic_name = var.config_sns_topic_name
@@ -228,7 +228,7 @@ module "config_baseline_eu-west-3" {
228228
module "config_baseline_sa-east-1" {
229229
source = "./modules/config-baseline"
230230
iam_role_arn = aws_iam_role.recorder.arn
231-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
231+
s3_bucket_name = local.audit_log_bucket_id
232232
s3_key_prefix = var.config_s3_bucket_key_prefix
233233
delivery_frequency = var.config_delivery_frequency
234234
sns_topic_name = var.config_sns_topic_name
@@ -241,7 +241,7 @@ module "config_baseline_sa-east-1" {
241241
module "config_baseline_us-east-1" {
242242
source = "./modules/config-baseline"
243243
iam_role_arn = aws_iam_role.recorder.arn
244-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
244+
s3_bucket_name = local.audit_log_bucket_id
245245
s3_key_prefix = var.config_s3_bucket_key_prefix
246246
delivery_frequency = var.config_delivery_frequency
247247
sns_topic_name = var.config_sns_topic_name
@@ -254,7 +254,7 @@ module "config_baseline_us-east-1" {
254254
module "config_baseline_us-east-2" {
255255
source = "./modules/config-baseline"
256256
iam_role_arn = aws_iam_role.recorder.arn
257-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
257+
s3_bucket_name = local.audit_log_bucket_id
258258
s3_key_prefix = var.config_s3_bucket_key_prefix
259259
delivery_frequency = var.config_delivery_frequency
260260
sns_topic_name = var.config_sns_topic_name
@@ -267,7 +267,7 @@ module "config_baseline_us-east-2" {
267267
module "config_baseline_us-west-1" {
268268
source = "./modules/config-baseline"
269269
iam_role_arn = aws_iam_role.recorder.arn
270-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
270+
s3_bucket_name = local.audit_log_bucket_id
271271
s3_key_prefix = var.config_s3_bucket_key_prefix
272272
delivery_frequency = var.config_delivery_frequency
273273
sns_topic_name = var.config_sns_topic_name
@@ -280,7 +280,7 @@ module "config_baseline_us-west-1" {
280280
module "config_baseline_us-west-2" {
281281
source = "./modules/config-baseline"
282282
iam_role_arn = aws_iam_role.recorder.arn
283-
s3_bucket_name = module.audit_log_bucket.this_bucket.id
283+
s3_bucket_name = local.audit_log_bucket_id
284284
s3_key_prefix = var.config_s3_bucket_key_prefix
285285
delivery_frequency = var.config_delivery_frequency
286286
sns_topic_name = var.config_sns_topic_name

examples/external-bucket/bucket.tf

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
resource "aws_s3_bucket" "logs" {
2+
bucket = var.audit_s3_bucket_name
3+
acl = "private"
4+
force_destroy = true
5+
}
6+
7+
resource "aws_s3_bucket_policy" "logs" {
8+
bucket = aws_s3_bucket.logs.id
9+
policy = <<END_OF_POLICY
10+
{
11+
"Version": "2012-10-17",
12+
"Statement": [
13+
{
14+
"Sid": "AWSCloudTrailAclCheckForConfig",
15+
"Effect": "Allow",
16+
"Principal": {"Service": "config.amazonaws.com"},
17+
"Action": "s3:GetBucketAcl",
18+
"Resource": "${aws_s3_bucket.logs.arn}"
19+
},
20+
{
21+
"Sid": " AWSCloudTrailWriteForConfig",
22+
"Effect": "Allow",
23+
"Principal": {"Service": "config.amazonaws.com"},
24+
"Action": "s3:PutObject",
25+
"Resource": "${aws_s3_bucket.logs.arn}/config/AWSLogs/${data.aws_caller_identity.current.account_id}/Config/*",
26+
"Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}}
27+
},
28+
{
29+
"Sid": "AWSCloudTrailAclCheckForCloudTrail",
30+
"Effect": "Allow",
31+
"Principal": {
32+
"Service": "cloudtrail.amazonaws.com"
33+
},
34+
"Action": "s3:GetBucketAcl",
35+
"Resource": "${aws_s3_bucket.logs.arn}"
36+
},
37+
{
38+
"Sid": "AWSCloudTrailWriteForCloudTrail",
39+
"Effect": "Allow",
40+
"Principal": {
41+
"Service": "cloudtrail.amazonaws.com"
42+
},
43+
"Action": "s3:PutObject",
44+
"Resource": "${aws_s3_bucket.logs.arn}/cloudtrail/AWSLogs/${data.aws_caller_identity.current.account_id}/*",
45+
"Condition": {
46+
"StringEquals": {
47+
"s3:x-amz-acl": "bucket-owner-full-control"
48+
}
49+
}
50+
}
51+
]
52+
}
53+
END_OF_POLICY
54+
}

examples/root-example/main.tf renamed to examples/external-bucket/main.tf

+8-3
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,18 @@ provider "aws" {
77
data "aws_caller_identity" "current" {
88
}
99

10-
module "root_example" {
10+
resource "aws_iam_user" "admin" {
11+
name = "admin"
12+
}
13+
14+
module "secure_baseline" {
1115
source = "../../"
1216

13-
audit_log_bucket_name = var.audit_s3_bucket_name
17+
audit_log_bucket_name = aws_s3_bucket.logs.id
18+
use_external_audit_log_bucket = true
1419
aws_account_id = data.aws_caller_identity.current.account_id
1520
region = var.region
16-
support_iam_role_principal_arn = var.support_iam_role_principal_arn
21+
support_iam_role_principal_arn = aws_iam_user.admin.arn
1722

1823
providers = {
1924
aws = aws

examples/root-example/variables.tf renamed to examples/external-bucket/variables.tf

-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ variable "audit_s3_bucket_name" {
88
description = "The name of the S3 bucket to store various audit logs."
99
}
1010

11-
variable "support_iam_role_principal_arn" {
12-
description = "The ARN of the IAM principal element by which the support role could be assumed."
13-
}
14-
1511
variable "region" {
1612
description = "The AWS region in which global resources are set up."
1713
default = "us-east-1"

0 commit comments

Comments
 (0)