kagarlickij
kagarlickij

Reputation: 8107

Terraform resources created with `for_each` - use in other Terraform scripts

I have terraform script that creates N security groups:

variable "security_groups" {
    default     = {
        "sg1" = "Security group 1"
        "sg2" = "Security group 2"
    }
}

resource "aws_security_group" "example" {
    for_each = var.security_groups

    name                   = each.key
    description            = each.value

    vpc_id                 = aws_vpc.example.id
    revoke_rules_on_delete = false

    egress {
        from_port   = 0
        to_port     = 0
        protocol    = "-1"
        cidr_blocks = ["0.0.0.0/0"]
    }
}

..and I have another Terraform script that creates IAM policy,

this one has to reference N Security groups created by first script in Resource section:

resource "aws_iam_policy" "operator_policy" {
  name        = "${var.iam_prefix}-operator"
  path        = "/"
  description = "Policy for operator"
  policy      = <<-EOF
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "ec2:AuthorizeSecurityGroupEgress",
                    "ec2:AuthorizeSecurityGroupIngress",
                    "ec2:UpdateSecurityGroupRuleDescriptionsEgress",
                    "ec2:UpdateSecurityGroupRuleDescriptionsIngress",
                    "ec2:RevokeSecurityGroupEgress",
                    "ec2:RevokeSecurityGroupIngress"
                ],
                "Effect": "Allow",
                "Resource": [
                    "sg1 ARN",
                    "sgN ARN"
                ]
            }
        ]
    }
    EOF
}

Is it feasible somehow?

Upvotes: 0

Views: 136

Answers (2)

Martin Atkins
Martin Atkins

Reputation: 74064

Rather than using string templates to generate JSON, it's more robust to generate the entire value using the jsonencode function, because then Terraform can evaluate the argument as a normal expression and be sure to generate a valid JSON representation of the result:

resource "aws_iam_policy" "operator_policy" {
  name        = "${var.iam_prefix}-operator"
  path        = "/"
  description = "Policy for operator"
  policy      = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "ec2:AuthorizeSecurityGroupEgress",
          "ec2:AuthorizeSecurityGroupIngress",
          "ec2:UpdateSecurityGroupRuleDescriptionsEgress",
          "ec2:UpdateSecurityGroupRuleDescriptionsIngress",
          "ec2:RevokeSecurityGroupEgress",
          "ec2:RevokeSecurityGroupIngress",
        ]
        Effect = "Allow"
        Resource = [
          "sg1 ARN",
          "sgN ARN",
        ]
      },
    ]
  })
}

As well as guaranteeing that the result will always be valid JSON syntax, using Terraform's expression language to build your policy value also means you can use all of Terraform's expression operators, including for expressions to read the arn attribute from each of your security groups:

resource "aws_iam_policy" "operator_policy" {
  name        = "${var.iam_prefix}-operator"
  path        = "/"
  description = "Policy for operator"
  policy      = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "ec2:AuthorizeSecurityGroupEgress",
          "ec2:AuthorizeSecurityGroupIngress",
          "ec2:UpdateSecurityGroupRuleDescriptionsEgress",
          "ec2:UpdateSecurityGroupRuleDescriptionsIngress",
          "ec2:RevokeSecurityGroupEgress",
          "ec2:RevokeSecurityGroupIngress",
        ]
        Effect = "Allow"
        Resource = [
          for sg in aws_security_group.example : sg.arn
        ],
      },
    ]
  })
}

Upvotes: 1

Marcin
Marcin

Reputation: 238081

You can use a combo of jsonencode with values and spat expression:

resource "aws_iam_policy" "operator_policy" {
  name        = "${var.iam_prefix}-operator"
  path        = "/"
  description = "Policy for operator"
  policy      = <<-EOF
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "ec2:AuthorizeSecurityGroupEgress",
                    "ec2:AuthorizeSecurityGroupIngress",
                    "ec2:UpdateSecurityGroupRuleDescriptionsEgress",
                    "ec2:UpdateSecurityGroupRuleDescriptionsIngress",
                    "ec2:RevokeSecurityGroupEgress",
                    "ec2:RevokeSecurityGroupIngress"
                ],
                "Effect": "Allow",
                "Resource": ${jsonencode(values(aws_security_group.example)[*].arn)}
            }
        ]
    }
    EOF
}

Upvotes: 1

Related Questions