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.82k stars 9.17k forks source link

S3 bucket policy malformed - Error putting S3 policy: MalformedPolicy: Policy has invalid resource #11158

Open ghost opened 4 years ago

ghost commented 4 years ago

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


Terraform Version

Terraform v0.11.11

Terraform Configuration Files

resource "aws_s3_bucket" "wdb" {
  bucket = "YYYYYYY"
  acl    = "private"

  tags {
    Name = "Wdb bucket"
  }
}

data "template_file" "wdb_policy_file" {
  template = "${file("${path.module}/policies/s3-wdb-shared-policy.json")}"

  vars {
    aws_wdb_bucket_arn = "${aws_s3_bucket.wdb.arn}"
  }
}

resource "aws_s3_bucket_policy" "wdb" {
  bucket = "${aws_s3_bucket.wdb.id}"

  policy = "${data.template_file.wdb_policy_file.rendered}"
}

----policy json
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Sid": "Wdb-CrossAccount",
          "Effect": "Allow",
          "Principal": {
              "AWS": "arn:aws:iam::XXXXXX:root"
          },
          "Action": "s3:*",
          "Resource": [
              "arn:aws:s3:::${aws_wdb_bucket_arn}/*",
              "arn:aws:s3:::${aws_wdb_bucket_arn}"
          ]
      }
  ]
}

...

Debug Output

aws_s3_bucket_policy.wdb: Error putting S3 policy: MalformedPolicy: Policy has invalid resource status code: 400,

Expected Behavior

Policy should be attached to bucket.

Actual Behavior

Error listed above is displayed

Steps to Reproduce

  1. terraform apply

Additional Context

If I take policy.json and apply it in AWS console via bucket policy it works.

zgre commented 4 years ago

Any update?

pquery commented 4 years ago

Is there any movement on this issue?

jav-12 commented 4 years ago

Wow, I'm having the same exact issue!. So seems to be a bug from version 0.11

`❯ terraform --version Terraform v0.12.28

ek8484 commented 4 years ago

Hey! Correct me if I'm wrong, but resources in the policy are really incorrect. There should be the bucket name (id) provided to get ARN as a result:

"Resource": [
              "arn:aws:s3:::${aws_s3_bucket.wdb.id}/*",
              "arn:aws:s3:::${aws_s3_bucket.wdb.id}"
          ]
raksa commented 3 years ago

Error: Policy has invalid resource comes from AWS when the policy json Resources has different target bucket's arn

 "Resource": [
              "arn:aws:s3:::${aws_wdb_bucket_arn}/*",
              `"arn:aws:s3:::${aws_wdb_bucket_arn}"`
          ]

Perhaps "arn:aws:s3:::${aws_wdb_bucket_arn}/*" have different result from "${aws_s3_bucket.wdb.arn}/*"

Let try this👇

 "Resource": [
              aws_s3_bucket.wdb.arn,
              "${aws_s3_bucket.wdb.arn}/*"
          ]
noahjahn commented 3 years ago

I'm also facing this issue on Terraform v1.0.9 and registry.terraform.io/hashicorp/aws v3.63.0.

Here is a condensed terraform config that I'm using to create a private S3 bucket and server files through a CloudFront CDN.

The policy with generated values from the created resources works when pasting the policy on the bucket from the console.

As a work-around, I'll just be placing the policy in the S3 bucket manually ... 🥶

locals {
  s3_origin_id              = "app-name-s3-origin-id"
  cache_optimized_policy_id = "658327ea-f89d-4fab-a63d-7e88639e58f6" # This is a managed policy provided by AWS
}

resource "aws_s3_bucket" "my_aws_s3_bucket" {
  bucket = "app-name"
  acl    = "private"
}

resource "aws_s3_bucket_public_access_block" "my_aws_s3_bucket_public_access_block" {
  bucket = aws_s3_bucket.my_aws_s3_bucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

output "myaws_s3_bucket_arn" {
  value = aws_s3_bucket.my_aws_s3_bucket.arn
}

output "my_aws_s3_bucket_name" {
  value = aws_s3_bucket.my_aws_s3_bucket.id
}

resource "aws_cloudfront_origin_access_identity" "my_aws_cloudfront_origin_access_identity" {}

resource "aws_cloudfront_distribution" "my_aws_cloudfront_distribution" {
  origin {
    domain_name = aws_s3_bucket.my_aws_s3_bucket.bucket_regional_domain_name
    origin_id   = local.s3_origin_id

    s3_origin_config {
      origin_access_identity = aws_cloudfront_origin_access_identity.my_aws_cloudfront_origin_access_identity.cloudfront_access_identity_path
    }
  }

  enabled         = true
  is_ipv6_enabled = true

  default_cache_behavior {
    target_origin_id       = local.s3_origin_id
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]
    cache_policy_id        = local.cache_optimized_policy_id
    compress               = true
    viewer_protocol_policy = "redirect-to-https"
  }

  price_class = "PriceClass_100"

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

resource "aws_s3_bucket_policy" "my_aws_s3_bucket_policy" {
  bucket = aws_s3_bucket.my_aws_s3_bucket.id
  policy = jsonencode({
    "Version" : "2008-10-17",
    "Statement" : [{
      "Effect" : "Allow",
      "Principal" : {
        "AWS" : "${aws_cloudfront_origin_access_identity.my_aws_cloudfront_origin_access_identity}"
      },
      "Action": "s3:GetObject",
      "Resource" : "${aws_s3_bucket.my_aws_s3_bucket.arn}/*"
    }]
  })
}

Here's the error message I get:

Error: Error putting S3 policy: MalformedPolicy: Invalid policy syntax.
      status code: 400, request id: ***, host id: ***

  with module.s3-and-cdn_resources.aws_s3_bucket_policy.my_aws_s3_bucket_policy,
  on modules/s3-and-cdn/main.tf line 64, in resource "aws_s3_bucket_policy" "my_aws_s3_bucket_policy":
  64: resource "aws_s3_bucket_policy" "my_aws_s3_bucket_policy" {
noahjahn commented 3 years ago

I'm also facing this issue on Terraform v1.0.9 and registry.terraform.io/hashicorp/aws v3.63.0.

Here is a condensed terraform config that I'm using to create a private S3 bucket and server files through a CloudFront CDN.

The policy with generated values from the created resources works when pasting the policy on the bucket from the console.

As a work-around, I'll just be placing the policy in the S3 bucket manually ... 🥶

locals {
  s3_origin_id              = "app-name-s3-origin-id"
  cache_optimized_policy_id = "658327ea-f89d-4fab-a63d-7e88639e58f6" # This is a managed policy provided by AWS
}

resource "aws_s3_bucket" "my_aws_s3_bucket" {
  bucket = "app-name"
  acl    = "private"
}

resource "aws_s3_bucket_public_access_block" "my_aws_s3_bucket_public_access_block" {
  bucket = aws_s3_bucket.my_aws_s3_bucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

output "myaws_s3_bucket_arn" {
  value = aws_s3_bucket.my_aws_s3_bucket.arn
}

output "my_aws_s3_bucket_name" {
  value = aws_s3_bucket.my_aws_s3_bucket.id
}

resource "aws_cloudfront_origin_access_identity" "my_aws_cloudfront_origin_access_identity" {}

resource "aws_cloudfront_distribution" "my_aws_cloudfront_distribution" {
  origin {
    domain_name = aws_s3_bucket.my_aws_s3_bucket.bucket_regional_domain_name
    origin_id   = local.s3_origin_id

    s3_origin_config {
      origin_access_identity = aws_cloudfront_origin_access_identity.my_aws_cloudfront_origin_access_identity.cloudfront_access_identity_path
    }
  }

  enabled         = true
  is_ipv6_enabled = true

  default_cache_behavior {
    target_origin_id       = local.s3_origin_id
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]
    cache_policy_id        = local.cache_optimized_policy_id
    compress               = true
    viewer_protocol_policy = "redirect-to-https"
  }

  price_class = "PriceClass_100"

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

resource "aws_s3_bucket_policy" "my_aws_s3_bucket_policy" {
  bucket = aws_s3_bucket.my_aws_s3_bucket.id
  policy = jsonencode({
    "Version" : "2008-10-17",
    "Statement" : [{
      "Effect" : "Allow",
      "Principal" : {
        "AWS" : "${aws_cloudfront_origin_access_identity.my_aws_cloudfront_origin_access_identity}"
      },
      "Action": "s3:GetObject",
      "Resource" : "${aws_s3_bucket.my_aws_s3_bucket.arn}/*"
    }]
  })
}

Here's the error message I get:

Error: Error putting S3 policy: MalformedPolicy: Invalid policy syntax.
      status code: 400, request id: ***, host id: ***

  with module.s3-and-cdn_resources.aws_s3_bucket_policy.my_aws_s3_bucket_policy,
  on modules/s3-and-cdn/main.tf line 64, in resource "aws_s3_bucket_policy" "my_aws_s3_bucket_policy":
  64: resource "aws_s3_bucket_policy" "my_aws_s3_bucket_policy" {

Whoops, a few more minutes after posting I realized my problem, sorry for the noise. I didn't use the iam_arn attribute in the policy. Changing "Principal" key in the policy fixed my issue:

"Principal" : {
  "AWS" : "${aws_cloudfront_origin_access_identity.my_aws_cloudfront_origin_access_identity.iam_arn}"
}
justinretzolk commented 2 years ago

Hey y'all 👋 Thank you for taking the time to file this issue, and for the continued discussion around it. It looks like this may be resolved based on the more recent comments; can anyone who was experiencing this confirm whether you're still experiencing this behavior?

noahh40 commented 2 years ago

I ran into this same error. Turns out I put an action variable in the Principal value.

markjfletcher commented 2 years ago

Same issue here, only solution was to use an inline policy

tpho commented 1 year ago

I hit this bug today finally.

maikokuppe commented 1 year ago

In my case the error appeared because I used two different buckets as resources like this:

      "Resource": [
          "arn:aws:s3:::myfirstbucket/*",
          "arn:aws:s3:::mysecondbucket/*"
      ],

The error disappeared when I removed one of them (no matter which one):

      "Resource": [
          "arn:aws:s3:::myfirstbucket/*"
      ],
danielksato commented 1 year ago

I ran into the same exact issue as @maikokuppe; the workaround that worked for me was separating the two Resource values into different Statement blocks.

mirela-nesic-symphony commented 1 year ago

Any updates on this issue?

paramsd1997 commented 3 months ago

Hi All, Any one have found any solution of this...................

cd83 commented 1 month ago

Signing in to revive this. Almost 5 years, still coming across this same problem.

nbcchen commented 3 weeks ago

In my case the error appeared because I used two different buckets as resources like this:

      "Resource": [
          "arn:aws:s3:::myfirstbucket/*",
          "arn:aws:s3:::mysecondbucket/*"
      ],

The error disappeared when I removed one of them (no matter which one):

      "Resource": [
          "arn:aws:s3:::myfirstbucket/*"
      ],

The above doesn't work for me. I tried this also

resources = ["*"]