Somethingwhatever
Somethingwhatever

Reputation: 1368

InsufficientS3BucketPolicyException::Incorrect S3 bucket policy is detected for bucket

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

Answers (1)

Helder Sepulveda
Helder Sepulveda

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...


the policy

I started breaking down your policy, also looking at others doing similar things, one good example:

https://github.com/cloud-custodian/cloud-custodian/blob/main/tests/terraform/cloudtrail_success_log_metric_filter/main.tf

            "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:
enter image description here


the change

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


s3_key_prefix

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

enter image description here


full code from my tests

all my code while I was troubleshooting is here:
https://github.com/heldersepu/hs-scripts/commits/master/TerraForm/InsufficientS3BucketPolicyException/main.tf

Upvotes: 0

Related Questions