CloudFormation can pull secrets and configuration values directly from AWS Systems Manager (SSM) Parameter Store, making your templates more dynamic and secure.

Let’s see this in action. Imagine you have a database password stored in SSM Parameter Store, and you want to use it in a CloudFormation template to configure an RDS instance.

Here’s how you’d store the password in SSM Parameter Store:

aws ssm put-parameter \
    --name "/my-app/db/password" \
    --value "supersecretpassword123!" \
    --type "SecureString"

Now, in your CloudFormation template, you can reference this parameter like so:

Resources:
  MyDatabaseInstance:
    Type: AWS::RDS::DBInstance
    Properties:
      DBInstanceIdentifier: my-database
      Engine: postgres
      MasterUsername: admin

      MasterUserPassword: "{{resolve:ssm:/my-app/db/password}}" # <-- Here's the magic

      AllocatedStorage: 20
      DBInstanceClass: db.t3.micro

When CloudFormation creates the MyDatabaseInstance resource, it automatically resolves the {{resolve:ssm:/my-app/db/password}} placeholder. It makes an API call to SSM Parameter Store, retrieves the value associated with /my-app/db/password, and substitutes it into the MasterUserPassword property. This avoids hardcoding sensitive information directly in your template, enhancing security.

The {{resolve:ssm:...}} syntax is a CloudFormation intrinsic function specifically designed for parameter lookups. It works for both String and SecureString parameter types. For SecureString parameters, CloudFormation automatically decrypts the value using KMS before passing it to the resource. You can also specify a specific KMS key ID if you used a custom key when storing the parameter.

Resources:
  MyDatabaseInstance:
    Type: AWS::RDS::DBInstance
    Properties:
      DBInstanceIdentifier: my-database
      Engine: postgres
      MasterUsername: admin

      MasterUserPassword: "{{resolve:ssm:/my-app/db/password:1}}" # <-- Version 1

      AllocatedStorage: 20
      DBInstanceClass: db.t3.micro

By specifying a version number (e.g., :1), you can ensure that CloudFormation uses a particular version of the parameter, which is useful for rollbacks or managing parameter updates independently of your stack. If you omit the version, CloudFormation uses the latest version of the parameter.

This mechanism isn’t limited to RDS. You can use SSM parameters for any CloudFormation property that accepts a string value, such as:

  • API Gateway authorizer secrets
  • Lambda function environment variables
  • EC2 user data scripts
  • S3 bucket policies
  • Any custom resource configuration

The key benefit is that you can update sensitive values or configuration settings in SSM Parameter Store without needing to modify and redeploy your CloudFormation stack. This separation of concerns allows for faster iteration on configuration and improved security posture.

When you reference a parameter, CloudFormation performs the lookup at deployment time. This means that if you update the parameter in SSM, the next time you update the stack (or create a new one), CloudFormation will fetch the new value. It does not retroactively update existing resources if the parameter changes after the stack has been created, unless you explicitly update the stack.

A common pitfall is forgetting to grant the CloudFormation service role the necessary permissions to read from SSM Parameter Store. Without ssm:GetParameter and ssm:GetParameters, the stack creation or update will fail with an access denied error.

The {{resolve:ssm:...}} syntax supports parameter paths with multiple levels, like /my-app/db/password, and also allows you to fetch multiple parameters at once using {{resolve:ssm-list:/my-app/config/*}}, which returns a JSON object containing all parameters under that path. This can be incredibly useful for managing a large number of related configuration settings.

You’ll next want to explore using SSM Parameter Store for application configurations, not just secrets, to achieve truly dynamic and manageable deployments.

Want structured learning?

Take the full Cloudformation course →