How to load parameter store values into an EC2's environment variables

In this article, I'm going to show you how to take all the parameters you have stored in the AWS Parameter store and load them into EC2 as environment variables.

It's pretty simple and I'll jump right into the code.

I created a shell script named: load_ssm_parameters.sh. For simplicity, I have the project and environment variables hardcoded below, but in reality, those values get set automatically from my EC2 instances tags.

#!/bin/bash

# instead of hard-coding these values, you could add them as environment vars
# see loading environment vars from tags
main_path="company_name/app_name"
environment="dev"
parameter_store_prefix="/${main_path}/${environment}"

For my parameters in the SSM Parameter store, my pattern is:

/company/project/environment/parameter_name, but you can easily shorten that to project/environment/parameter_name, simply change the parameter_store_prefix to match your path.

No matter how many levels you make the path, the last section of the path will be returned by the split("/") method and talking the last element of the array via [-1] of the split("/")[-1]

For example if your parameter is something like company_name/web_app/dev/app_connection_string and it has a value of "abcd". The script will pull the app_connection_string and the value making an environment variable of :

APP_CONNECTION_STRING=abcd

Note the ascii_upcase in the jq script, which transforms the Name part into upper case.

This section of the code will execute the aws ssm command to pull back the name/value pairs of all the elements it finds in the parameter_store_prefix path.  It will decrypt any of the values that are encrypted (such as database connection strings).

The jq section will transform the json data blocks into export name=value (there could be zero or many export lines). All of the results will be stored in the export_statement variable which will be evaluated (loaded into memory) in another block of code.


# note to execute this statement, the EC2 instance will need the correct permissions
# AmazonSSMReadOnlyAccess is appropriate
# add the appropriate policy to the role attached to the EC2 instance#
# the split("/")[-1] will grab the last parameter as the "name" for the variable
# all varable names are converted to upper case for ENV consistency
export_statement=$(aws ssm get-parameters-by-path \
--path "${parameter_store_prefix}" \
--region us-east-1 --recursive \
--with-decrypt \
| jq -r '.Parameters[] | "export " + (.Name | split("/")[-1] | ascii_upcase | gsub("-"; "_")) + "=\"" + .Value + "\""' \
)

 

The eval statement will take everything that is loaded into the export_statement and effectively load the variables into memory.


eval $export_statement

In order to persist the values after a reboot, I essentially need to make sure that the variables are loaded/exported during the boot process.

You can accomplish this by placing the export statements in a script and placing the script into the /etc/profile.d directory. Anything in that directory is launched during the boot process. I'll have everything ready for waiting for me.

Quick note: make sure you give the script execution access:


# export them to a file so they are reloaded on reboots
sudo cat -s > /etc/profile.d/load_ssm_parameters.sh << EOF

$export_statement

EOF

# make sure the script can execute when/if a reboot happens
chmod +x /etc/profile.d/load_ssm_parameters.sh

The full script looks like this:

#!/bin/bash

sudo yum update -y
# using jq for parsing
sudo yum install -y jq

# instead of hard-coding these values, you could add them as environment vars
# see loading environment vars from tags
main_path="company_name/app_name"
environment="dev"
parameter_store_prefix="/${main_path}/${environment}"

# note to execute this statement, the EC2 instance will need the correct permissions
# AmazonSSMReadOnlyAccess is appropriate
# add the appropriate policy to the role attached to the EC2 instance#
# the split("/")[-1] will grab the last parameter as the "name" for the variable
# all varable names are converted to upper case for ENV consistency
export_statement=$(aws ssm get-parameters-by-path \
--path "${parameter_store_prefix}" \
--region us-east-1 --recursive \
--with-decrypt \
| jq -r '.Parameters[] | "export " + (.Name | split("/")[-1] | ascii_upcase | gsub("-"; "_")) + "=\"" + .Value + "\""' \
)


# eval the statements to load them into memory
# the above script addthem in a pattern of
# export parameter_name=parameter_value
eval $export_statement

# export them to a file so they are reloaded on reboots
sudo cat -s > /etc/profile.d/load_ssm_parameters.sh << EOF

$export_statement

EOF

# make sure the script can execute when/if a reboot happens
chmod +x /etc/profile.d/load_ssm_parameters.sh


Troubleshooting

 

If your parameters aren't loading correctly, it's typically either a permissions issue (the EC2 instance needs to have access to read the parameter store). Be sure to add the correct permissions to the role that is bound to the EC2 instance.

If you aren't getting a permissions issue, try running the asw command directly to see what it's returning. It may be a simple type or path issue.

You can execute the command directly like the following:


aws ssm get-parameters-by-path \
--path "${parameter_store_prefix}" \
--region us-east-1 --recursive \
--with-decrypt

Image Credit: Eric Prouzet on Unsplash

Leave a comment

Please note that we won't show your email to others, or use it for sending unwanted emails. We will only use it to render your Gravatar image and to validate you as a real person.