João Pacheco
João Pacheco

Reputation: 67

Terraform: How to separate actions for different identifiers inside the same iam policy document statement

I am trying to apply different actions for different IAM users, through Terraform, using the aws_iam_policy_document data source. Let's take as an example the following KMS Key policy statement:

data "aws_iam_policy_document" "kms_key_policy" {
  statement {
    sid = "Allow use of the key"

    principals {
      type        = "AWS"
      identifiers = var.A == true ? [ARN1, ARN2] : [ARN1]
    }

    actions = [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
    ]
    resources = ["*"]
  }
}

In the policy above I want to restrict the first two actions to the ARN2, but keep the ARN1 with all the actions that are originally in the actions block. Of course that I could just add another statement and separate both logics (as shown below) but I was trying to keep all the logic into the same statement and avoid repeating code:

statement {
    sid = "Allow ARN1 use of the key"

    principals {
      type        = "AWS"
      identifiers = [ARN1]
    }

    actions = [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
    ]
    resources = ["*"]
  }
statement {
    sid = "Allow ARN2 use of the key"

    principals {
      type        = "AWS"
      identifiers = var.A == true ? [ARN2] : []
    }

    actions = [
        "kms:Encrypt",
        "kms:Decrypt"
    ]
    resources = ["*"]
  }

I've already tried to add a condition similar to what is being used to check for the presence of ARN2 (in case var A is defined) but I was restricting ARN1 actions with the ARN2 one's (if ARN2 was present), as can be observed below:

actions = var.A == true ? ["kms:Encrypt", "kms:Decrypt"] : ["kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey"]

How could I separate the actions for the different principal identifiers ARNs inside the same statement?

Upvotes: 1

Views: 1064

Answers (1)

Semafoor
Semafoor

Reputation: 2032

What you're describing is not possible, as you can't make the list of actions a function of the principal during policy evaluation. That's not a Terraform limitation but how these AWS statements work. The conditionals you write here are evaluated when you apply the Terraform code, not during policy evaluation.

You never want to allow the same list of actions for both principals, regardless of the value of var.A, so you will need always need at least two statements. I hope this make sense to you.

I'd propose something like this:

statement {
  sid = "AllowEncryptDecrypt"
  principals {
    type        = "AWS"
    identifiers = var.A == true ? [ARN1, ARN2] : [ARN1]
  }
  actions = [
    "kms:Encrypt",
    "kms:Decrypt",
  ]
  resources = ["*"]
}

statement {
  sid = "AllowOtherKeyUse"
  principals {
    type        = "AWS"
    identifiers = [ARN1]
  }
  actions = [
    "kms:ReEncrypt*",
    "kms:GenerateDataKey*",
    "kms:DescribeKey",
  ]
  resources = ["*"]
}

I'd argue there's no real repetition here, as there's no overlap between the lists of actions.

Upvotes: 2

Related Questions