Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tf.state saved without empty principal block for s3 bucket policy #18525

Closed
benvand opened this issue Jul 24, 2018 · 2 comments
Closed

tf.state saved without empty principal block for s3 bucket policy #18525

benvand opened this issue Jul 24, 2018 · 2 comments

Comments

@benvand
Copy link

benvand commented Jul 24, 2018

Terraform Version

Terraform v0.11.7
+ provider.archive v1.0.0
+ provider.aws v1.9.0

Terraform Configuration Files

modules/s3-document-bucket/main.tf
So we have a simple module to create a bucket and attach a policy giving read/ write perms to specified roles based on arns passed in as variables.

variable "bucket_name" {
  description = "(Required) A name our S3 bucket."
}

variable "read_object_roles" {
  type        = "list"
  description = "A list of role ARNs to apply get object permssions to."
}

variable "write_object_roles" {
  type        = "list"
  description = "A list of role ARNs to apply S3:PutObject and S3:PutObjectACL permissions to."
}

data "aws_iam_policy_document" "document_bucket_policy_document" {
  # Assign read roles
  statement {
    sid = ""
    effect = "Allow"

    principals {
      identifiers = "${var.read_object_roles}"
      type        = "AWS"
    }

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

    resources = [
      
      "arn:aws:s3:::${var.bucket_name}/*",
      "arn:aws:s3:::${var.bucket_name}",
    ]
  }
  # Assign write roles
  statement {
    sid = ""
    effect = "Allow"

    principals {
      identifiers = "${var.write_object_roles}"
      type        = "AWS"
    }

    actions = [
      "s3:PutObject",
      "s3:PutObjectAcl",
    ]

    resources = [
      "arn:aws:s3:::${var.bucket_name}/*",
      "arn:aws:s3:::${var.bucket_name}",
    ]
  }
}

resource "aws_s3_bucket" "document_bucket" {
  bucket = "${var.bucket_name}"
  acl    = "private"

  versioning {
    enabled = true
  }

  # Apply policy to bucket
  policy = "${data.aws_iam_policy_document.document_bucket_policy_document.json}"
}

main.tf
We call the module, in the first instance it's fine, creates the policy, saves it to the remote state file etc. The problem arises when we have an empty list as our principal variable (read_only_bucket.write_object_roles)

module "read_write_bucket" {
  source             = "../../modules/s3-document-bucket"
  bucket_name        = "scratch-bucket"
  read_object_roles  = ["arn:aws:iam::${var.account_id}:role/readers"]
  write_object_roles = ["arn:aws:iam::${var.account_id}:role/writers"]
}

module "read_only_bucket" {
  source             = "../../modules/s3-document-bucket"
  bucket_name        = "some-read-only-bucket"
  read_object_roles  = ["arn:aws:iam::${var.account_id}:role/readers"]
  write_object_roles = []
}

Output of terraform plan

Terraform plan shows there is a change to make and is saying it will add an empty principal block. It doesn't appear to complete this action because running plan, then apply then plan yields the same message.

{
  "Statement": [
    {
      "Action": [
        "s3:GetObject",
        "s3:ListBucket",
        "s3:GetBucketLocation"
      ],
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789101:role/readers"
      },
      "Resource": [
        "arn:aws:s3:::some-read-only-bucket/*",
        "arn:aws:s3:::some-read-only-bucket"
      ],
      "Sid": ""
    },
    {
      "Action": [
        "s3:PutObjectAcl",
        "s3:PutObject"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::some-read-only-bucket/*",
        "arn:aws:s3:::some-read-only-bucket"
      ],
      "Sid": ""
    }
  ],
  "Version": "2012-10-17"
}

=>

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket",
        "s3:GetBucketLocation"
      ],
      "Resource": [
        "arn:aws:s3:::some-read-only-bucket/*",
        "arn:aws:s3:::some-read-only-bucket"
      ],
      "Principal": {
        "AWS": "arn:aws:iam::123456789101:role/readers"
      }
    },
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": [
        "s3:PutObjectAcl",
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::some-read-only-bucket/*",
        "arn:aws:s3:::some-read-only-bucket"
      ],
      "Principal": {
        "AWS": []
      }
    }
  ]
}

What's happening

The state file gets saved without a principal block because it would have been empty.
The plan gets generated with an empty principal block.
There's always a mismatch.

Additional Context

It looks like this might be a known issue:
https://www.terraform.io/docs/providers/aws/r/s3_bucket.html#policy

if the policy document is not specific enough (but still valid), Terraform may view the policy as constantly changing in a terraform plan.

However... This is slightly more of a problem than the issues referenced below. In those, resource, action and principal list variables are converted to strings if they contain a single value. In my case the principal block is removed altogether when no principal is specified. I can't replicate this in my terraform because I can't conditionally remove the principal block

Can anyone suggest a work around until 0.12 ? https://www.hashicorp.com/blog/terraform-0-1-2-preview

References

#5613
#4948

@ghost
Copy link

ghost commented Jul 24, 2018

This issue has been automatically migrated to hashicorp/terraform-provider-aws#5311 because it looks like an issue with that provider. If you believe this is not an issue with the provider, please reply to hashicorp/terraform-provider-aws#5311.

@ghost ghost closed this as completed Jul 24, 2018
@ghost
Copy link

ghost commented Apr 2, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked and limited conversation to collaborators Apr 2, 2020
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants