Sabo Boz
Sabo Boz

Reputation: 2575

Syntax for conditions in aws_iam_policy resources in terraform

I am currently trying to implement an aws_iam_policy in terraform that looks like:

resource "aws_iam_policy" "policyName" {
  name        = "policyName"
  path        = "/"
 
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        NotAction = [
          "iam:*"
        ]
        Resource = "*"
 
        Condition = {
          test = "StringEquals"
          variable = "s3:prefix"
          values = [
            "home/"
          ]
        }
      }
    ]
  })
}

However, when I try to deploy this in an environment I'm using within a team, I get an error saying there are syntax errors with this (the logs only point out the starting line and nowhere else). When I take out the Condition block the error disappears, so I know it's something to do with the condition. I have checked the terraform documentation and they do not have an = after the condition, but when I remove the = I get an error saying the = is expected. Would anyone know of the correct syntax/the right place to look for documentation regarding this (as stated previously the documentation at https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document doesn't work for me)?

Upvotes: 8

Views: 26591

Answers (3)

Saurabh Saxena
Saurabh Saxena

Reputation: 131

As an alternative to Joel Van Hollebeke's answer, a simple change to the Condition block in the original document would also work.

Instead of :

    Condition = {
      test = "StringEquals"
      variable = "s3:prefix"
      values = [
        "home/"
      ]
    }

Use this:

   Condition = {
      "StringEquals" = {
        "s3:prefix" = "home/"
      }
    }

Having said this, "aws_iam_policy_document" is still the most recommended way of doing this in terraform.

Upvotes: 13

Saurabh
Saurabh

Reputation: 6940

Extending Saurabh Saxena's answer, you can also use variables in the condition block

variable "s3_location" {
  default = "home"
  description = "S3 bucket prefix location"
}

resource "aws_iam_policy" "policyName" {
  name        = "policyName"
  path        = "/"
 
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        NotAction = [
          "iam:*"
        ]
        Resource = "*"
 
        Condition = {
          "StringEquals" = {
            "s3:prefix" = "${var.s3_location}/"
          }
        }
      }
    ]
  })
}

Upvotes: 0

Joel Van Hollebeke
Joel Van Hollebeke

Reputation: 770

I would try an aws_iam_policy_document data block, like the following example:

data "aws_iam_policy_document" "example" {

  statement {

    not_actions = [
      "iam:*",
    ]

    effect = "Allow"

    resources = [
      "*",
    ]

    condition {
      test     = "StringEquals"
      variable = "s3:prefix"
      values = [
        "home/"
      ]
    }
  }
}

And then add a aws_iam_policy resource that references this data source:

resource "aws_iam_policy" "policyName" {
  name   = "policyName"
  path   = "/"
  policy = data.aws_iam_policy_document.example.json
}

In my experience, this pattern has yielded the best validation when provisioning IAM policies.

Upvotes: 8

Related Questions