'Is there a way to add CORS rule to Terraform aws_s3_bucket data source?

I have an existing bucket that was not created via Terraform. I'm currently setting a policy on that bucket for additional access rights. I need to add a cors_rule to the bucket, but everything I'm finding suggests that you need to create the resource in order to add the cors rule. Is there a way to add a cors_rule to an existing bucket data source?

data "aws_s3_bucket" "my_bucket" {
  bucket = "my-bucket"

  # This produces a failure on plan
  cors_rule {
    allowed_headers = ["*"]
    allowed_methods = ["GET", "HEAD"]
    allowed_origins = [
      "https://example.my-website.com"
    ]
    expose_headers  = [
      "Access-Control-Allow-Origin",
      "ETag"
    ]
    max_age_seconds = 3000
  }
}

resource "aws_s3_bucket_policy" "allow_access" {
  bucket = data.aws_s3_bucket.my_bucket.id
  policy = data.aws_iam_policy_document.allow_access.json
}

data "aws_iam_policy_document" "allow_access" {
  statement {
    sid = "Access"

    principals {
      type = "AWS"
      identifiers = ["arn:aws:iam::123456789012:user/test"]
    }

    actions = [
      "s3:GetObject",
      "s3:GetBucketLocation",
      "s3:ListBucket",
    ]

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

plan error



Solution 1:[1]

You are in so much luck. Just today / yesterday version 4.0.0 of the AWS provider was released.
That new provider version refactored a lot in regards to S3 bucket handling. You now have a standalone s3_bucket_cors_configuration resource instead of CORS settings directly on the aws_s3_bucket resource. That means you can now configure the CORS settings (and many others settings) without actually having the bucket itself in your state.

resource "aws_s3_bucket_cors_configuration" "example" {
  bucket = aws_s3_bucket.example.bucket

  cors_rule {
    allowed_headers = ["*"]
    allowed_methods = ["PUT", "POST"]
    allowed_origins = ["https://s3-website-test.hashicorp.com"]
    expose_headers  = ["ETag"]
    max_age_seconds = 3000
  }

  cors_rule {
    allowed_methods = ["GET"]
    allowed_origins = ["*"]
  }
}

The only caveat is that you would need to upgrade to 4.0.0 of the AWS provider with all the breaking changes that come with it.

Solution 2:[2]

resource "aws_s3_bucket" "my_bucket" {
  bucket = "my-bucket"

  cors_rule {
    allowed_headers = ["*"]
    allowed_methods = ["PUT", "POST", "DELETE", "GET"]
    allowed_origins = ["*"]
    expose_headers  = []
  }
}

This works for me with version 3.7

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Supervision