AWS Cloud Operations & Migrations Blog

Integrating AWS CloudFormation with AWS Systems Manager Parameter Store

AWS CloudFormation has always allowed you to customize your templates by using parameters for runtime input values. Parameters make your template code dynamically configurable, improving the reusability of your code. Previously, the only ways you could specify values for these parameters were to pass the plaintext values as arguments to the CloudFormation API, or hard code them in the template using ‘default’ values. This posed the following limitations:

  1. There was no centralized place to define/update your parameters (which may contain secrets, configuration data, etc.) and then import them into CloudFormation.
  2. When changing parameters, you had to either slightly rewrite your template code or pass new parameter values when doing stack update operation.

We are pleased to announce the integration of CloudFormation with AWS Systems Manager Parameter Store which provides solutions to the above restrictions. In this blog, I explain how you can use Systems Manager parameters in your CloudFormation templates to simplify stack updates involving parameters and achieve consistency by using values stored in Parameter Store. With this integration, your code remains untouched while the stack update operation automatically picks up the latest parameter store value.

How Systems Manager parameters work in CloudFormation

You can use the existing Parameters section of your CloudFormation template to define Systems Manager parameters, along with other parameters. Systems Manager parameters are a unique type that is different from existing parameters because they refer to actual values in the Parameter Store. The value for this type of parameter would be the Systems Manager (SSM) parameter key instead of a string or other value. CloudFormation will fetch values stored against these keys in Systems Manager in your account and use them for the current stack operation. If the parameter being referenced in the template does not exist in Systems Manager, a synchronous validation error is thrown. Also, if you have defined any parameter value validations (AllowedValues, AllowedPattern, etc.) for Systems Manager parameters, they will be performed against SSM keys which are given as input values for template parameters, not actual values stored in Systems Manager.

Parameters stored in Systems Manager are mutable. Any time you use a template containing Systems Manager parameters to create/update your stacks, CloudFormation uses the values for these Systems Manager parameters at the time of the create/update operation. So, as parameters are updated in Systems Manager, you can have the new value of the parameter take effect by just executing a stack update operation. The Parameters section in the output for Describe API will show an additional ‘ResolvedValue’ field that contains the resolved value of the Systems Manager parameter that was used for the last stack operation.

New Systems Manager parameter types supported in CloudFormation

CloudFormation parameters already support certain AWS specific types. SSM parameter types will be an addition to these types. New parameter types introduced in CloudFormation are:

  • AWS::SSM::Parameter::Name
  • AWS::SSM::Parameter::Value<String>
  • AWS::SSM::Parameter::Value<List<String>>
  • AWS::SSM::Parameter::Value<Any AWS type>

The first one in the list is used to pass the name of the parameter key as-is. CloudFormation will not fetch the value stored against it. For example, you can use this type to validate that the parameter exists in Parameter Store. For all others, the value is fetched from Systems Manager with the type defined in the trailing angle brackets <>. For now, you can only use plaintext strings or list of strings. CloudFormation will support the Parameter Store ‘SecureString’ type in a later release.

How to Use SSM types in CloudFormation

As mentioned earlier, SSM parameter types are used in template to reference existing Systems Manager parameters. Let’s look at a couple example scenarios.

Example 1:

Let’s say you are deploying a CloudFormation stack in both Development and Production. You are planning to use smaller instance types in Development. You don’t want to remember the instance types to be used in your CloudFormation template whenever you redeploy from one environment to another. The data (parameter value for the instance type parameter) can be maintained separately from the code (template). This example shows the end-to-end steps for using Systems Manger parameters for this use-case.

# Create a parameters for Dev and Prod environments in Systems Manager Parameter Store
aws ssm put-parameter --name myEC2TypeDev --type String --value “t2.small”
aws ssm put-parameter --name myEC2TypeProd --type String --value “m4.large”

# Reference/use existing Systems Manager Parameter in CloudFormation
Parameters:
  InstanceType :
    Type : 'AWS::SSM::Parameter::Value<String>'
    Default: myEC2TypeDev
  KeyName :
    Type : 'AWS::SSM::Parameter::Value<AWS::EC2::KeyPair::KeyName>'
    Default: myEC2Key
  AmiId:
    Type: 'AWS::EC2::Image::Id'
    Default: 'ami-60b6c60a'
    
Resources :
  Instance :
    Type : 'AWS::EC2::Instance'
    Properties :
       Type : !Ref InstanceType
       KeyName : !Ref KeyName
       ImageId : !Ref AmiId 
# Call create-stack for Dev environment by passing SSM parameter key as template parameter value
aws cloudformation create-stack --stack-name S1 --template-body <above-template>

# Call create-stack for Prod environment by passing SSM parameter key as template parameter value
aws cloudformation create-stack --stack-name S1 --template-body <above-template> --parameters ParameterKey=InstanceType,ParameterValue=myEC2TypeProd

Systems Manager console – All SSM parameters under this account are displayed.

CloudFormation console – Stack list page where selected stack is using SSM parameters.

CloudFormation console – Stack detail page for stack using SSM parameters.

Example 2:

Consider the use case of updating Amazon Machine Image (AMI) IDs for the EC2 instances in your CloudFormation templates. Normally, you might map AMI IDs to specific instance types and Regions. Then to update these, you would manually change them in each of your templates. Or you would be using a custom resource with an AWS Lambda function that gets the IDs of the latest AMIs for the Region and instance type that you’re using. Arguably, neither of these methods is very convenient.

Systems Manger Parameter Store team recently launched an easy way to retrieve the latest AMI IDs for your template. Hierarchical public parameters supported by Parameter Store can also be referenced in a CloudFormation template similar to the one used in Example 1. You can use the public parameter variable for the Windows AMI ID in your template. You don’t need to worry about how to fetch the latest AMI IDs. This SSM parameter will be updated whenever there is a newer version available. Whenever you decide to update the EC2 instances in your CloudFormation template to use the new AMI ID, you just call update-stack API on the stack. It will automatically fetch the latest value from Parameter Store. Also, note that for hierarchical parameters, you need to provide the full path of the parameter name.

# Use public Systems Manager Parameter
Parameters :
  LatestAmiId :
    Type : 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
    Default: ‘/aws/service/ami-windows-latest/Windows_Server-2016-English-Core-Containers’

Resources :
  Instance :
    Type : 'AWS::EC2::Instance'
    Properties :
      ImageId : !Ref LatestAmiId
# Create-stack CLI call
aws cloudformation create-stack --stack-name S1 --template-body <above-template>

# Describe stack output’s ‘Parameters’ section for this stack
aws cloudformation describe-stacks --stack-name S1
…
            "Parameters": [
                {
                    "ParameterValue": "/aws/service/ami-windows-latest/Windows_Server-2016-English-Core-Containers",
                    "ResolvedValue": "ami-ba9c05c0",
                    "ParameterKey": "LatestAmiId"
                }

            ]
…

Summary

By leveraging the CloudFormation integration with Systems Manager Parameter Store, you can make your templates more reusable and generic by storing and managing your runtime configuration and parameters centrally and securely. This, in turn, can make your stack operations simpler and more consistent, by clearly delineating the separation of infrastructure configuration and infrastructure code from each other.

The feature is now available in all AWS Regions!


About the Author

Anuradha Garg is a software developer on the AWS CloudFormation team where she works on developing new features for the service. Outside work, she is a travel enthusiast and loves exploring new things.