AWS SSM Parameter Setting Strategy in Terraform

We use AWS SSM parameters to store specifics of our deployed infrastructure, and to share those specifics between terraform projects deployed in an environment.

AWS SSM Parameter Setting Strategy in Terraform
Photo by Diane Picchiottino / Unsplash

We use AWS SSM parameters to store specifics of our deployed infrastructure, and to share those specifics between terraform projects deployed in an environment.

Setting SSM parameters can happen in one of two ways:

  1. Set by Terraform, after the deployment of infrastructure (an output, used by other things)
  2. Set by a human (an input, used to define something that differs in each environment (say, a VPC CIDR)

Setting the parameter in code is relatively easy, we use a resource block and make sure to overwrite the value on each apply (so that we know its up to date)

resource "aws_ssm_parameter" "test_vpc" {
  name      = "/tfvars/network/test_vpc/vpc-id"
  type      = "SecureString"
  value     = aws_vpc.test_vpc.id
  overwrite = true
}
Simple SSM parameter resource

But humans are not to great at setting a parameters, especially not in a specific path, with a specific format.

Helping the Humans

To aid the humans here, we do two things.

Shell example

First, we provide a text file in the project repository with an AWS ssm command with details of how we expect the parameter to be created:

aws ssm put-parameter \
	--name "/tfvars/network/test_vpc/vpc_name" \
    --type "SecureString" \
    --description "The name of the test_vpc" \
    --overwrite \
    --value "testing123"
Shell line showing the expected parameter details

This way, we have an example (we don't commit the other environments VALUE, but can use the command in AWS CloudShell to set in the environment.

TF HCL conditions and outputs

Next, we do some checking in the Terraform HCL for human-set values to resolve common mistakes when setting the values, and make it easier to catch them if they do happen.

First, spaces in the SSM Parameter is a common mistaken, particularly when copy/pasting values into the console.

data "aws_ssm_parameter" "vpc_name" {
  name = "/tfvars/network/test_vpc/vpc_name"
  lifecycle {
    postcondition {
      condition     = trimspace(self.value) == self.value
      error_message = "There is a leading or trailing blank space."
    }
  }
}
Adding postconditions helps prevents human error when copying leading/trailing spaces

Second, we can use an output so that we see the value in our terraform plan/applies to catch other mistakes.

# Output user set ssm parameters for clarity of plans and applies
output "vpc_name" {
  value = nonsensitive(data.aws_ssm_parameter.vpc_name.value)
}
Outputs print the value of the SSM parameters to help human plan reviewer catch mistakes