skip to Main Content

Been stuck at this for countless hours now.

This command works perfectly fine for me via the terminal:

aws ssm get-parameter --name "/something/i/know/exists" --query "Parameter.Value" --output text

Output:

subnet-whatIwouldExpect

But setting it as a variable inside Terraform has been a different story completely.

(I have been happily using Terraform plan/apply/destroy etc)

data "external" "ssm_parameter_value" {
  program = ["bash", "-c", <<-EOF
    result=$(aws ssm get-parameter --name "/something/i/know/exists" --query "Parameter.Value" --output text)
    echo "{"result": "$result"}"
  EOF
  ]
}

output "ssm_parameter_result" {
  value = data.external.ssm_parameter_value.result
}

When I try terraform refresh I get:

ssm_parameter_result = tomap({
  "result" = ""
})

This is extremely frustrating, and I don’t know what I’m doing wrong.

This is my entire file:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.34.0"
    }
  }
  
  required_version = ">= 0.14.9"
}

provider "aws" {
  region = "eu-west-2"
  default_tags {
    tags = local.common_tags
  }
}

data "aws_caller_identity" "current" {}

data "aws_region" "current" {}

# Execute AWS CLI command to get SSM parameter value
data "external" "ssm_parameter_value" {
  program = ["bash", "-c", <<-EOF
    result=$(aws ssm get-parameter --name "/something/i/know/exists" --query "Parameter.Value" --output text)
    echo "{"result": "$result"}"
  EOF
  ]
}

output "ssm_parameter_result" {
  value = data.external.ssm_parameter_value.result
}

Edit:

I am aware of data "aws_ssm_parameter" "example" { name = "/A/B/C" }

However, this fails with ParameterNotFound if it doesn’t exist on AWS.

And it does not seem as though this is surpsa

I want to be able to utilise the value of

data.external.ssm_parameter_value.result

to drive the creation/non-creation of other resources later on:

e.g.

resource "aws_security_group_rule" "example" {  
  count = data.external.ssm_parameter_value.result != "" ? 1 : 0
  type              = "ingress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  security_group_id = data.external.ssm_parameter_value.result["result"]
  source_security_group_id = aws_security_group.another-sg.id
  
  description = "All Traffic from Lambda"
}

2

Answers


  1. There is no reason to shell out to the command line and use the AWS CLI tool just to look up an SSM parameter value in your Terraform code. That’s a very convoluted, and error-prone way to get the value.

    You are already using the AWS Terraform provider, and it is already connected to AWS, so why jump through extra hoops with the AWS CLI tool to read a value from AWS?

    Just replace your data "external" "ssm_parameter_value" with the following:

    data "aws_ssm_parameter" "my_parameter" {
      name = "/something/i/know/exists"
    }
    

    And then reference the value with aws_ssm_parameter.my_parameter.value, for example:

    output "ssm_parameter_result" {
      value = aws_ssm_parameter.my_parameter.value
    }
    
    Login or Signup to reply.
  2. As Mark explained in his answer you should, when possible, use resource specific data sources. But using the external data source is a valid alternative in all other scenarios.

    The external data source mandates that the program output must be a JSON object for which the value is a serialized string. So in this example, you could do:

    # Execute AWS CLI command to get SSM parameter value
    data "external" "ssm_parameter_value" {
      program = ["bash", "-c", <<-EOF
        aws ssm get-parameter --name "PARAMETER_NAME" --query "Parameter.Value" --output text | xargs -I {} jq -r -n --arg param {} '{"param":($param|tojson)}'
      EOF
      ]
    }
    
    output "ssm_parameter_result" {
      value = jsondecode(data.external.ssm_parameter_value.result.param)
    }
    
    $ terraform apply
    ...
    ssm_parameter_result = "foo"
    

    Note that this approach requires jq for the creation of the JSON object.

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