How to avoid S3 bucket policy conflict

alt-f4

I am currently having two (maybe conflicting) S3 bucket policies, which show a permanent difference on Terraform. Before I show parts of the code, I will try to give an overview of the structure.

I am currently using a module, which:

  1. Takes IAM Role & an S3 Bucket as inputs
  2. Attaches S3 Bucket policy to the inputted role
  3. Attaches S3 Bucket (allowing VPC) policy to the inputted S3 bucket

I have created some code (snippet and not full code) to illustrate how this looks like for the module.

The policies look like:

# S3 Policy to be attached to the ROLE
data "aws_iam_policy_document" "foo_iam_s3_policy" {
  statement {
    effect    = "Allow"
    resources = ["${data. s3_bucket.s3_bucket.arn}/*"]
    actions   = ["s3:GetObject", "s3:GetObjectVersion"]
  }
  statement {
    effect    = "Allow"
    resources = [data.s3_bucket.s3_bucket.arn]
    actions   = ["s3:*"]
  }
}

# VPC Policy to be attached to the BUCKET
data "aws_iam_policy_document" "foo_vpc_policy" {
  statement {
    sid       = "VPCAllow"
    effect    = "Allow"
    resources = [data.s3_bucket.s3_bucket.arn, "${data.s3_bucket.s3_bucket.arn}/*"]
    actions   = ["s3:GetObject", "s3:GetObjectVersion"]
    condition {
      test     = "StringEquals"
      variable = "aws:SourceVpc"
      values   = [var.foo_vpc]
    }
    principals {
      type        = "*"
      identifiers = ["*"]
    }
  }
}

The policy attachments look like:

# Turn policy into a resource to be able to use ARN
resource "aws_iam_policy" "foo_iam_policy_s3" {
  name        = "foo-s3-${var.s3_bucket_name}"
  description = "IAM policy for foo on s3"
  policy      = data.aws_iam_policy_document.foo_iam_s3_policy.json
}

# Attaches s3 bucket policy to IAM Role
resource "aws_iam_role_policy_attachment" "foo_attach_s3_policy" {
  role       = data.aws_iam_role.foo_role.name
  policy_arn = aws_iam_policy.foo_iam_policy_s3.arn
}

# Attach foo vpc policy to bucket
resource "s3_bucket_policy" "foo_vpc_policy" {
  bucket = data.s3_bucket.s3_bucket.id
  policy = data.aws_iam_policy_document.foo_vpc_policy.json
}

Now let's step outside of the module, where the S3 bucket (the one I mentioned that will be inputted into the module) is created, and where another policy needs to be attached to it (the S3 bucket). So outside of the module, we:

  1. Provide an S3 bucket to the aforementioned module as input (alongside the IAM Role)
  2. Create a policy to allow some IAM Role to put objects in the aforementioned bucket
  3. Attach the created policy to the bucket

The policy looks like:

# Create policy to allow bar to put objects in the bucket
    data "aws_iam_policy_document" "bucket_policy_bar" {
      statement {
        sid       = "Bar IAM access"
        effect    = "Allow"
        resources = [module.s3_bucket.bucket_arn, "${module. s3_bucket.bucket_arn}/*"]
        actions   = ["s3:PutObject", "s3:GetObject", "s3:ListBucket"]
        principals {
          type        = "AWS"
          identifiers = [var.bar_iam]
        }
      }
    }

And its attachment looks like:

    # Attach Bar bucket policy
    resource "s3_bucket_policy" "attach_s3_bucket_bar_policy" {
      bucket = module.s3_bucket.bucket_name
      policy = data.aws_iam_policy_document.bucket_policy_bar.json
    }

(For more context: Basically foo is a database that needs VPC and s3 attachment to role to operate on the bucket and bar is an external service that needs to write data to the bucket)

What is going wrong

When I try to plan/apply, Terraform shows that there is always change, and shows an overwrite between the S3 bucket policy of bar (bucket_policy_bar) and the VPC policy attached inside the module (foo_vpc_policy).

In fact the error I am getting kind of sounds like what is described here:

The usage of this resource conflicts with the aws_iam_policy_attachment resource and will permanently show a difference if both are defined.

But I am attaching policies to S3 and not to a role, so I am not sure if this warning applies to my case.

Why are my policies conflicting? And how can I avoid this conflict?

EDIT: For clarification, I have a single S3 bucket, to which I need to attach two policies. One that allows VPC access (foo_vpc_policy, which gets created inside the module) and another one (bucket_policy_bar) that allows IAM role to put objects in the bucket

Marcin

there is always change

That is correct. aws_s3_bucket_policy sets new policy on the bucket. It does not add new statements to it.

Since you are invoking aws_s3_bucket_policy twice for same bucket, first time in module.s3_bucket module, then second time in parent module (I guess), the parent module will simply attempt to set new policy on the bucket. When you perform terraform apply/plan again, the terraform will detect that the policy defined in module.s3_bucket is different, and will try to update it. So you end up basically with a circle, where each apply will change the bucket policy to new one.

I'm not aware of a terraform resource which would allow you to update (i.e. add new statements) to an existing bucket policy. Thus I would try to re-factor your design so that you execute aws_s3_bucket_policy only once with all the statements that you require.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How to set S3 bucket policy to (mostly) private when object acl is public?

S3 bucket policy, how to ALLOW a IAM group from another account?

How do I unlock or delete an AWS S3 bucket that inadvertently locked with a bucket policy?

How do I do an OR condition in an S3 bucket policy?

Incorrect S3 bucket policy is detected for bucket in CloudFormation

How to properly setup an IAM execution role and a bucket policy for getting lambda writing to a public read S3 bucket?

AWS S3 Bucket policy public. How to make object private?

AWS S3 Bucket Policy Whitelist

S3 CORS policy for public bucket

How do I create an S3 bucket policy from a template in Terraform 0.12?

How do I grant cross account access to an encrypted bucket with a simple s3 bucket policy?

How to avoid cycle error when setting an S3 bucket policy with a template that depends on the bucket name?

How to create correct S3 bucket policy to enable read access to a file only if they know the path

AWS: How to update an existing S3 bucket-policy via CloudFormation?

How to grant access only to the Root Account User for an S3 bucket with IAM Policy AWS?

Amazon S3 Bucket Policy Public

Why is this s3 Bucket policy invalid?

How should I set up my bucket policy so I can deploy to S3?

Terraform - attach policy to s3 bucket

How to specify AWS S3 bucket policy

How to add OriginAccessIdentity to AWS S3 Bucket Policy using troposphere

How can I add IP restrictions to s3 bucket(in the bucket Policy) already having a User restriction

AWS S3 Bucket Policy: How to grant access to EC2 instance?

AWS S3 empty bucket policy

How to get bucket policy using Airflow s3 hook

How to upload to S3 bucket with public policy

S3 bucket access restriction with bucket policy

AWS S3 Bucket Policy is not valid

AWS S3 bucket policy with condition