Terraform - para directiva en JSON

Terraform - para directiva en JSON

Estoy intentando realizar un bucle sobre los valores de cadena en un bloque de recursos de política de IAM para permitir la autenticación de IAM rds. Mi definición de recurso es:

  resource "aws_iam_policy" "rds_iam_authentication"{
  name    = "${title(var.environment)}RdsIamAuthentication"
  policy  = templatefile(
    "${path.module}/iam_policy.json",
    {
      aws_account_id        = data.aws_caller_identity.current.account_id
      region         = var.region
      environment           = var.environment
      iam_rds_pg_role_name  = var.iam_rds_pg_role_name
    }
  )
}

La definición de variable de iam_rds_pg_role_namein terraform.tfvarses la siguiente:

region                  = "eu-west-3"
environment             = "env_name"
iam_rds_pg_role_name    = ["read_only_role", "full_role"]
aws_account_id          = "1234567890"

Y el archivo de plantilla de política de IAM es:

{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Effect": "Allow",
          "Action": [
              "rds-db:connect"
          ],
          "Resource": [
            %{ for rds_role in iam_rds_pg_role_name ~}
              "arn:aws:rds-db:${region}:${aws_account_id}:dbuser:*/${rds_role}"
            %{ endfor ~}
          ]
      }
  ]
}

Recibo un error que dice

Error: "política" contiene un JSON no válido: carácter no válido '"' después del elemento de matriz

Estoy bastante seguro de que el problema está relacionado con la codificación json; sin embargo, al intentar jsonencodela definición de arn en el json como se muestra a continuación, el error aún está presente:

%{ for rds_role in iam_rds_pg_role_name ~}
    jsonencode("arn:aws:rds-db:${region}:${aws_account_id}:dbuser:*/${rds_role}")}
%{ endfor ~}

Agradecería que me explicaran lo que me falta o que alguien me indique la dirección correcta.

gracias de antemano

Respuesta1

En su archivo de plantilla de política de IAM, falta una coma al final de los elementos de Resource:

...
        "Resource": [
            %{ for rds_role in iam_rds_pg_role_name ~}
              "arn:aws:rds-db:${region}:${aws_account_id}:dbuser:*/${rds_role}",
                                                  there should be a comma here ^
            %{ endfor ~}
          ]
...

Puede recorrer tanto el índice como el elemento en iam_rds_pg_role_namey agregar una coma si el índice es menor que length(iam_rds_pg_role_name) - 1:

...
        "Resource": [
            %{ for index, rds_role in iam_rds_pg_role_name ~}
              "arn:aws:rds-db:${region}:${aws_account_id}:dbuser:*/${rds_role}"%{ if idx < length(iam_rds_pg_role_name) - 1 },%{ endif }
            %{ endfor ~}
          ]
...

Resultado:

Terraform will perform the following actions:

  # aws_iam_policy.rds_iam_authentication will be created
  + resource "aws_iam_policy" "rds_iam_authentication" {
      + arn         = (known after apply)
      + id          = (known after apply)
      + name        = "Env_nameRdsIamAuthentication"
      + name_prefix = (known after apply)
      + path        = "/"
      + policy      = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = [
                          + "rds-db:connect",
                        ]
                      + Effect   = "Allow"
                      + Resource = [
                          + "arn:aws:rds-db:eu-west-3:1234567890:dbuser:*/read_only_role",
                          + "arn:aws:rds-db:eu-west-3:1234567890:dbuser:*/full_role",
                        ]
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + policy_id   = (known after apply)
      + tags_all    = (known after apply)
    }

información relacionada