Reputation: 1368
I am creating a Cloudtrail trail and an S3 bucket to store all my logs. My trail has to be an org level trail
and a multi region trail. I am setting up the S3 bucket policy from these AWS docs. My kms key policy allows cloudtrail to kms:GenerateDataKey*", "kms:DescribeKey", "kms:Decrypt
.
resource "aws_kms_key" "cloudtrail_kms_key" {
description = "KMS key for Cloudtrail S3 Bucket"
enable_key_rotation = true
multi_region = true
}
resource "aws_kms_key_policy" "cloudtrail_kms_key_policy" {
key_id = aws_kms_key.cloudtrail_kms_key.key_id
policy = jsonencode({
Version = "2012-10-17",
Id = "cloudtrail-kms-key-policy",
Statement : [
{
Sid = "Enable IAM User Permissions"
Effect = "Allow"
Principal = { AWS = "arn:aws:iam::${var.aws_account_id}:root" }
Action = "kms:*"
Resource = "*"
},
{
Sid = "Permitted KMS Key Services"
Effect = "Allow"
Principal = {
Service = ["cloudtrail.amazonaws.com"]
}
Action = ["kms:GenerateDataKey*", "kms:DescribeKey", "kms:Decrypt"]
Resource = "*",
"Condition" : {
"StringEquals" : {
"aws:SourceArn" : "arn:aws:cloudtrail:${var.aws_region}:${var.aws_account_id}:trail/${var.trail_name}"
},
"StringLike": {
"kms:EncryptionContext:aws:cloudtrail:arn": "arn:aws:cloudtrail:*:${var.aws_account_id}:trail/*"
}
}
}
]
})
}
resource "aws_cloudtrail" "trail" {
depends_on = [aws_s3_bucket_policy.cloudtrail_bucket_policy]
name = var.trail_name
s3_bucket_name = aws_s3_bucket.cloudtrail_bucket.id
is_organization_trail = true
is_multi_region_trail = true
kms_key_id = aws_kms_key.cloudtrail_kms_key.arn
enable_log_file_validation = true
}
resource "aws_s3_bucket" "cloudtrail_bucket" {
bucket = "${var.bucket_name}"
}
resource "aws_s3_bucket_ownership_controls" "cloudtrail_bucket_ownership_controls" {
bucket = aws_s3_bucket.cloudtrail_bucket.id
rule {
object_ownership = "BucketOwnerEnforced"
}
}
#Link to IAM policy : https://docs.aws.amazon.com/awscloudtrail/latest/userguide/create-s3-bucket-policy-for-cloudtrail.html#org-trail-bucket-policy
data "aws_iam_policy_document" "cloudtrail_bucket_policy" {
statement {
sid = "AWSCloudTrailAclCheck"
effect = "Allow"
principals {
type = "Service"
identifiers = ["cloudtrail.amazonaws.com"]
}
actions = ["s3:GetBucketAcl"]
resources = [aws_s3_bucket.cloudtrail_bucket.arn]
condition {
test = "StringEquals"
variable = "aws:SourceArn"
values = ["arn:aws:cloudtrail:${var.aws_region}:${var.aws_account_id}:trail/${var.trail_name}"]
}
}
statement {
sid = "AWSCloudTrailWrite"
effect = "Allow"
principals {
type = "Service"
identifiers = ["cloudtrail.amazonaws.com"]
}
actions = ["s3:PutObject"]
resources = ["${aws_s3_bucket.cloudtrail_bucket.arn}/AWSLogs/${var.aws_account_id}/*"]
condition {
test = "StringEquals"
variable = "s3:x-amz-acl"
values = ["bucket-owner-full-control"]
}
condition {
test = "StringEquals"
variable = "aws:SourceArn"
values = ["arn:aws:cloudtrail:${var.aws_region}:${var.aws_account_id}:trail/${var.trail_name}"]
}
}
statement {
sid = "AllowOrganizationTrailToPutObjects"
effect = "Allow"
principals {
type = "Service"
identifiers = ["cloudtrail.amazonaws.com"]
}
actions = ["s3:PutObject"]
resources = ["${aws_s3_bucket.cloudtrail_bucket.arn}/AWSLogs/${var.organization_id}/*"]
condition {
test = "StringEquals"
variable = "s3:x-amz-acl"
values = ["bucket-owner-full-control"]
}
condition {
test = "StringEquals"
variable = "aws:SourceArn"
values = ["arn:aws:cloudtrail:${var.aws_region}:${var.aws_account_id}:trail/${var.trail_name}"]
}
}
}
resource "aws_s3_bucket_policy" "cloudtrail_bucket_policy" {
bucket = aws_s3_bucket.cloudtrail_bucket.id
policy = data.aws_iam_policy_document.cloudtrail_bucket_policy.json
}
Yet I keep running into the following error :
Error: creating CloudTrail Trail (org-logs): operation error CloudTrail: CreateTrail, https response error StatusCode: 400, RequestID: 42aed73c-100f-43cb-b094-cd5d615bde1e, InsufficientS3BucketPolicyException:
Incorrect S3 bucket policy is detected for bucket: cloudtrail-production-us-west-2-042518407502-ls (Service: AWSCloudTrail; Status Code: 400; Error Code: InsufficientS3BucketPolicyException; Request ID: 422be9b4-75da-4a97-8012-a80b99a9942a; Proxy: null)
Just as an additional point: I am indeed deploying this to the delegated administrator account so I know that is not an issue.
What am I doing wrong?
Upvotes: 3
Views: 788
Reputation: 17664
Let me start by saying I was able to reproduce exactly your same error:
InsufficientS3BucketPolicyException: Incorrect S3 bucket policy is detected for bucket
only difference in my test I set is_organization_trail
to false...
I started breaking down your policy, also looking at others doing similar things, one good example:
"Sid": "AWSCloudTrailWrite20150319",
"Effect": "Allow",
"Principal": {
"Service": "cloudtrail.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::${aws_s3_bucket.success-1.bucket}/*",
So I changed your first statement (AWSCloudTrailWrite
) to match that:
resources = ["${aws_s3_bucket.cloudtrail_bucket.arn}/*"]
After that no more errors and a structure was created in the bucket:
the difference in the line we changed:
["${aws_s3_bucket.cloudtrail_bucket.arn}/*"]
VS
["${aws_s3_bucket.cloudtrail_bucket.arn}/prefix/AWSLogs/${var.aws_account_id}/*"]
... maybe that prefix
is not supposed to be there
Your resource "aws_cloudtrail"
does not have a prefix defined, that is done with s3_key_prefix
we can add that, and my code now looks like:
resource "aws_cloudtrail" "trail" {
depends_on = [aws_s3_bucket_policy.cloudtrail_bucket_policy]
name = var.trail_name
s3_bucket_name = aws_s3_bucket.cloudtrail_bucket.id
is_organization_trail = false
is_multi_region_trail = true
kms_key_id = aws_kms_key.cloudtrail_kms_key.arn
enable_log_file_validation = true
s3_key_prefix = "prefix"
}
bring the resource back to the original and it all applies correctly
and the bucket now has that "prefix" in the structure
all my code while I was troubleshooting is here:
https://github.com/heldersepu/hs-scripts/commits/master/TerraForm/InsufficientS3BucketPolicyException/main.tf
Upvotes: 0