hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.76k stars 9.12k forks source link

Bug in AWS Config Delivery Channel #8655

Open ghost opened 5 years ago

ghost commented 5 years ago

This issue was originally opened by @stsraymond as hashicorp/terraform#21325. It was migrated here as a result of the provider split. The original body of the issue is below.


Terraform Version

...version 0.11.13

Terraform Configuration Files

...resource "aws_config_configuration_recorder" "default" {
  name = "default"
  role_arn = "${var.config_role_arn}"

  recording_group {
    all_supported                 = true
    include_global_resource_types = "${var.global_resource}"
  }
}

resource "aws_config_delivery_channel" "default" {
  s3_bucket_name = "${var.s3_bucket}"

  depends_on = ["aws_config_configuration_recorder.default"]
}

Debug Output

Crash Output


* aws_config_delivery_channel.default: Creating Delivery Channel failed: InsufficientDeliveryPolicyException: Insufficient delivery policy to s3 bucket: config-bucket-427771644408, unable to write to bucket, provided s3 key prefix is 'null'.
-->```

### Expected Behavior
<!--
AWS Config is enabled
-->

### Actual Behavior
<!--
The code fails
What actually happened?
-->

### Steps to Reproduce
<!--
1. `terraform init`
2. `terraform apply`
-->

### Additional Context
<!--
The code work in Singapore Region but fail in HK region
-->

### References
<!--
Are there any other GitHub issues (open or closed) or Pull Requests that should be linked here? For example:

- hashicorp/terraform#6017

-->
tdmalone commented 5 years ago

Related: #8654

henrikpingelallcloud commented 5 years ago

I had the same error message with aws_config_delivery_channel and it turned out that it was caused by a missing permission in the s3 bucket policy.

stsraymond commented 5 years ago

Hi henrikpingelallcloud,

Could you share the s3 bucket policy?

I use the same bucket policy which works in Singapore region but not in HK region

Reference :https://docs.aws.amazon.com/config/latest/developerguide/s3-bucket-policy.html

sonianara commented 5 years ago

@henrikpingelallcloud Can you please share the modifications to your s3 bucket policy? I'm running into the same issue.

henrikpingelallcloud commented 5 years ago

This s3 bucket policy was missing in my case: { "Version": "2012-10-17", "Statement": [ { "Sid": "AWSConfigBucketPermissionsCheck", "Effect": "Allow", "Principal": { "Service": [ "config.amazonaws.com" ] }, "Action": "s3:GetBucketAcl", "Resource": "arn:aws:s3:::${bucket_name}" }, { "Sid": " AWSConfigBucketDelivery", "Effect": "Allow", "Principal": { "Service": [ "config.amazonaws.com" ] }, "Action": "s3:PutObject", "Resource": [ ${aws_config_ressources} ], "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } } } ] }

EvanGertis commented 3 years ago

I'm running into the same issue I tried using: https://registry.terraform.io/modules/trussworks/config/aws/latest. When I ran apply I got Error: Creating Delivery Channel failed: InsufficientDeliveryPolicyException: Insufficient delivery policy to s3 bucket: my-aws-logs, unable to write to bucket, provided s3 key prefix is 'config'.

EvanGertis commented 3 years ago

Has anyone been able to get this to work the policy from @henrikpingelallcloud did not work for me.

EvanGertis commented 3 years ago

This example works

resource "aws_config_delivery_channel" "foo" {
  name           = "example"
  s3_bucket_name = aws_s3_bucket.b.bucket
  depends_on     = [aws_config_configuration_recorder.foo]
}

resource "aws_s3_bucket" "b" {
  bucket        = "example-awsconfig1234567788"
  force_destroy = true
}

resource "aws_config_configuration_recorder" "foo" {
  name     = "example"
  role_arn = aws_iam_role.r.arn
}

resource "aws_iam_role" "r" {
  name = "awsconfig-example"

  assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "config.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
POLICY
}

resource "aws_iam_role_policy" "p" {
  name = "awsconfig-example"
  role = aws_iam_role.r.id

  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "s3:*"
      ],
      "Effect": "Allow",
      "Resource": [
        "${aws_s3_bucket.b.arn}",
        "${aws_s3_bucket.b.arn}/*"
      ]
    }
  ]
}
POLICY
}

I would change your code to match this. My guess is that the policy statement isn't being parsed properly. I might look more into this later.

djsd123 commented 3 years ago

I was getting the error: Creating Delivery Channel failed: InsufficientDeliveryPolicyException: Insufficient delivery policy to s3 bucket: config-recorder-XXXX, unable to write to bucket, provided s3 key prefix is 'null', provided kms key is 'null'.

Similar to @EvanGertis 👍, I did:

resource "aws_iam_service_linked_role" "config_recorder" {
  aws_service_name = "config.amazonaws.com"
}

resource "aws_config_configuration_recorder" "config_recorder" {
  name     = "config-recorder"
  role_arn = aws_iam_service_linked_role.config_recorder.arn

  recording_group {
    include_global_resource_types = true
  }
}

resource "aws_config_delivery_channel" "config_recorder_delivery_channel" {
  depends_on = [aws_config_configuration_recorder.config_recorder]

  name           = "config-delivery-channel"
  s3_bucket_name = aws_s3_bucket.config_recorder.id
  sns_topic_arn  = aws_sns_topic.config_recorder.arn

  snapshot_delivery_properties {
    delivery_frequency = "TwentyFour_Hours"
  }
}

resource "aws_s3_bucket" "config_recorder" {
  bucket = "config-recorder"
  acl    = "log-delivery-write"

  lifecycle {
    prevent_destroy = true
  }

  lifecycle_rule {
    id      = "log"
    enabled = true

    transition {
      days          = 90
      storage_class = "GLACIER"
    }
  }
}

resource "aws_s3_bucket_policy" "config" {
  bucket = aws_s3_bucket.config_recorder.id
  policy = data.aws_iam_policy_document.config_recorder.json
}

resource "aws_sns_topic" "config_recorder" {
  name = "config-recorder"
}

data "aws_iam_policy_document" "config_recorder" {
  statement {
    sid = "DenyUnsecuredTransport"
    effect = "Allow"

    actions = [
      "s3:*",
    ]

    condition {
      test = "Bool"
      variable = "aws:SecureTransport"

      values = [
        "true",
      ]
    }

    principals {
      type        = "Service"
      identifiers = [aws_iam_service_linked_role.config_recorder.aws_service_name]
    }

    resources = [
      aws_s3_bucket.config_recorder.arn,
      "${aws_s3_bucket.config_recorder.arn}/*",
    ]
  }
}

Which worked a treat 💯

karollynecosta commented 2 years ago

For me It was solved by adding s3_bucket_name in code:

resource "aws_config_delivery_channel" "f" {
  name           = "config-to-s3"
  s3_bucket_name = aws_s3_bucket.s3-for-config.bucket

  snapshot_delivery_properties {
    delivery_frequency = var.snapshot_frequency
  }
  depends_on = [aws_config_configuration_recorder.f]
}
Andrea-Gallicchio commented 1 year ago

I'm still not able to send the AWS Config logs from Account A to an S3 Bucket in Account B.

This is the policy of my S3 Bucket in Account B:

data "aws_iam_policy_document" "config" {
  statement {
    sid       = "AWSConfigBucketPermissionsCheck"
    effect    = "Allow"
    resources = ["${aws_s3_bucket.config.arn}"]
    actions   = ["s3:GetBucketAcl"]

    condition {
      test     = "StringEquals"
      variable = "AWS:SourceAccount"
      values = [
        "xxxxxxx"
      ]
    }

    principals {
      type        = "Service"
      identifiers = ["config.amazonaws.com"]
    }
  }

  statement {
    sid       = "AWSConfigBucketExistenceCheck"
    effect    = "Allow"
    resources = ["${aws_s3_bucket.config.arn}"]
    actions   = ["s3:ListBucket"]

    condition {
      test     = "StringEquals"
      variable = "AWS:SourceAccount"
      values = [
        "xxxxxxx"
      ]
    }

    principals {
      type        = "Service"
      identifiers = ["config.amazonaws.com"]
    }
  }

  statement {
    sid    = "AWSConfigBucketDelivery"
    effect = "Allow"
    resources = [
      format("%s/AWSLogs/ACCOUNT_ID/Config/*}", aws_s3_bucket.config.arn)
    ]
    actions = ["s3:PutObject", "s3:PutObjectACL"]

    condition {
      test     = "StringEquals"
      variable = "AWS:SourceAccount"
      values = [
         xxxxx
      ]
    }

    condition {
      test     = "StringEquals"
      variable = "s3:x-amz-acl"
      values   = ["bucket-owner-full-control"]
    }

    principals {
      type        = "Service"
      identifiers = ["config.amazonaws.com"]
    }
  }
}

And this is the policy of the IAM Role used by AWS Config in Account A:

data "aws_iam_policy_document" "this" {
  statement {
    effect  = "Allow"
    actions = ["s3:PutObject", "s3:PutObjectAcl"]
    resources = [
      format("arn:aws:s3:::%s/AWSLogs/%s/*", var.aws_config_s3_bucket_name, data.aws_caller_identity.current.account_id)
    ]
  condition {
      test     = "StringEquals"
      variable = "s3:x-amz-acl"
      values   = ["bucket-owner-full-control"]
    }
  }
  statement {
    effect  = "Allow"
    actions = ["s3:GetBucketAcl"]
    resources = [
      format("arn:aws:s3:::%s", var.aws_config_s3_bucket_name)
    ]
  }
  statement {
    effect  = "Allow"
    actions = ["s3:ListBucket"]
    resources = [
      format("arn:aws:s3:::%s", var.aws_config_s3_bucket_name)
    ]
  }
}

The error that I get from Cloudtrail logs is always InsufficientDeliveryPolicyException. Any hints?

Thanks