skip to Main Content

I want to create multiple aws_iam_policy_document resources with for_each, to be later assumed by several roles, as follows:

# Policy to allow services to assume the role
data "aws_iam_policy_document" "this" {
  for_each           = var.lambda_configuration
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type = "Service"

      identifiers = [
        "lambda.amazonaws.com",
        "apigateway.amazonaws.com",
      ]
    }
  }
}

# IAM role for executing the Lambda function
resource "aws_iam_role" "this" {
  for_each           = var.lambda_configuration
  name               = "my_lambda_${each.key}_Executor_Role"
  description        = "Role for executing my_lambda-${each.key} function"
  assume_role_policy = data.aws_iam_policy_document.assume_role_policy_[each.key].json
}

How should I interpolate this

assume_role_policy = data.aws_iam_policy_document.assume_role_policy_[each.key].json

to make the correct matching with the roles?

2

Answers


  1. The correct syntax:

    data.aws_iam_policy_document.this[each.key].json
    

    Note that this is not interpolation, as you mentioned in your question. It is just a value lookup. And I have no idea where you got assume_role_policy_ from, but that is not valid HCL syntax.

    Login or Signup to reply.
  2. This seems like a good situation for Chaining for_each Between Resources, which (subjectively) tends to lead to a configuration where it’s easier for an unfamiliar reader to follow the way data is flowing between the resources.

    data "aws_iam_policy_document" "this" {
      for_each = var.lambda_configuration
    
      statement {
        actions = ["sts:AssumeRole"]
    
        principals {
          type = "Service"
    
          identifiers = [
            "lambda.amazonaws.com",
            "apigateway.amazonaws.com",
          ]
        }
      }
    }
    
    # IAM role for executing the Lambda function
    resource "aws_iam_role" "this" {
      for_each = data.aws_iam_policy_document.this
    
      name               = "my_lambda_${each.key}_Executor_Role"
      description        = "Role for executing my_lambda-${each.key} function"
      assume_role_policy = each.value.json
    }
    

    Using the first resource itself as the for_each for the second one means that the two will always have exactly the same keys (because a resource with for_each appears in expressions as a map of objects using the keys from the for_each map), and that each.value inside the second block refers to the corresponding instance of the first block.

    This has essentially the same behavior as using the index operator to select an element from data.aws_iam_policy_document.this using each.key, but makes the relationship between these two resources a little more direct and so (again, subjectively) easier to read and maintain in future.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search