Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a string in JSON format in Terraform variables

I am creating some resources using the for_each method on Terraform version 0.14.15. The resource has an attirbute, input_parameters that takes a string in JSON format as its value. I am defining this value in a map variable utilizing separate objects. The value I am specifying as a string in JSON format, and I am getting an error upon execution that I need to declare a string. Any insight on fixing this error would be helpful. Below is how I have my resource and variable declared.

Resource

resource "aws_config_config_rule" "managed_rules" {
  for_each         = var.managed_rules
  name             = each.value.name
  description      = each.value.description
  input_parameters = each.value.input_parameters

  source {
    owner             = each.value.owner
    source_identifier = each.value.source_identifier
  }

  depends_on = [aws_config_configuration_recorder.config_recorder]
}

Variable

variable "managed_rules" {
  type = map(object({
    name              = string
    description       = string
    owner             = string
    source_identifier = string
# Is there a variable for strings in JSON format?
    input_parameters  = string
  }))
  default = {
    "1" = {
      name              = "alb-http-to-https-redirection-check"
      description       = "Checks whether HTTP to HTTPS redirection is configured on all HTTP listeners of Application Load Balancers. The rule is NON_COMPLIANT if one or more HTTP listeners of Application Load Balancer do not have HTTP to HTTPS redirection configured."
      owner             = "AWS"
      source_identifier = "ALB_HTTP_TO_HTTPS_REDIRECTION_CHECK"
      input_parameters = {
        "MaximumExecutionFrequency" : "TwentyFour_Hours",
      }
  }

Error

This default value is not compatible with the variable's type constraint:
element "2": attribute "input_parameters": string required.

After updating code with jsonencode function and changing input_parameters to any, this is the error:

    This default value is not compatible with the variable's type constraint:
collection elements cannot be unified.
like image 291
Dave Michaels Avatar asked Mar 31 '26 19:03

Dave Michaels


2 Answers

You have a couple things going on here:

  1. The resource requires input_parameters to be a JSON-encoded string
  2. You have the variable type as a string
  3. You're passing an object type into the variable that only accepts a string type

So (2) and (3) are conflicting. At some point, you have to convert your object into a JSON string. You can either do that before passing it in as an input variable, or change your input variable to accept objects and convert the object to JSON when providing it to the resource.

I'd choose the second option because it's more intuitive to pass the object into the module instead of a string. So, try this:

resource "aws_config_config_rule" "managed_rules" {
  for_each         = var.managed_rules
  name             = each.value.name
  description      = each.value.description
  input_parameters = jsonencode(each.value.input_parameters)

  source {
    owner             = each.value.owner
    source_identifier = each.value.source_identifier
  }

  depends_on = [aws_config_configuration_recorder.config_recorder]
}


variable "managed_rules" {
  type = map(object({
    name              = string
    description       = string
    owner             = string
    source_identifier = string
# Is there a variable for strings in JSON format?
    input_parameters  = any
  }))
  default = {
    "1" = {
      name              = "alb-http-to-https-redirection-check"
      description       = "Checks whether HTTP to HTTPS redirection is configured on all HTTP listeners of Application Load Balancers. The rule is NON_COMPLIANT if one or more HTTP listeners of Application Load Balancer do not have HTTP to HTTPS redirection configured."
      owner             = "AWS"
      source_identifier = "ALB_HTTP_TO_HTTPS_REDIRECTION_CHECK"
      input_parameters = {
        "MaximumExecutionFrequency" : "TwentyFour_Hours",
      }
  }

Note that I've used jsonencode in the resource's input_parameters and I've changed the variable type for that field to any (so it will accept an object of any structure).

like image 92
Jordan Avatar answered Apr 03 '26 09:04

Jordan


To add to Jordan's answer. I Had a similar concern when trying to add a json policy to a module.

I used the any object type in place of the string object type.

Here's how I fixed it:

Module main.tf

resource "aws_ecr_repository_policy" "main" {
  repository = var.repository_name
  policy     = var.repository_policy
}

Module variables.tf

variable "repository_name" {
  type        = string
  description = "Name of the repository."
}

variable "repository_policy" {
  type        = any
  description = "The policy document. This is a JSON formatted string."
}

Resource Creation main.tf

# ECR Repository for container images
module "ecr_repository_1" {
  source = "../../../../modules/aws/ecr-repository"

  ecr_repository_name  = var.ecr_repository_name.1
  image_tag_mutability = var.image_tag_mutability
  image_scan_on_push   = var.image_scan_on_push
  tag_environment      = local.tag_environment
  tag_terraform        = local.tag_terraform.true
}

# ECR Repository policies
module "ecr_repository_policy_1" {
  source = "../../../../modules/aws/ecr-repository-policy"

  repository_name   = var.ecr_repository_name.1
  repository_policy = var.repository_policy.1
}

Resource creation variables.tf

variable "ecr_repository_name" {
  type        = map(string)
  description = "Name of the repository."
  default = {
    "1" = "my-backend-api"
  }
}

variable "image_tag_mutability" {
  type        = string
  description = "The tag mutability setting for the repository. Must be one of: MUTABLE or IMMUTABLE. Defaults to MUTABLE."
  default     = "MUTABLE"
}

variable "image_scan_on_push" {
  type        = bool
  description = "Indicates whether images are scanned after being pushed to the repository (true) or not scanned (false)."
  default     = true
}

variable "repository_policy" {
  type        = any
  description = "The policy document. This is a JSON formatted string."
  default = {
    "1" = <<EOF
          {
              "Version": "2008-10-17",
              "Statement": [
                  {
                      "Sid": "new policy",
                      "Effect": "Allow",
                      "Principal": "*",
                      "Action": [
                          "ecr:GetDownloadUrlForLayer",
                          "ecr:BatchGetImage",
                          "ecr:BatchCheckLayerAvailability",
                          "ecr:PutImage",
                          "ecr:InitiateLayerUpload",
                          "ecr:UploadLayerPart",
                          "ecr:CompleteLayerUpload",
                          "ecr:DescribeRepositories",
                          "ecr:GetRepositoryPolicy",
                          "ecr:ListImages",
                          "ecr:DeleteRepository",
                          "ecr:BatchDeleteImage",
                          "ecr:SetRepositoryPolicy",
                          "ecr:DeleteRepositoryPolicy"
                      ]
                  }
              ]
          }
          EOF
  }
}
like image 26
Promise Preston Avatar answered Apr 03 '26 09:04

Promise Preston