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
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:And then reference the value with
aws_ssm_parameter.my_parameter.value
, for example: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:
Note that this approach requires
jq
for the creation of the JSON object.