Referencing AWS Parameter Store's Secure String in CloudFormation template

Stuck with the usage of SecureString from AWS Parameter Store. I am trying to refer to the database password as:

DatabasePassword:
    Type: AWS::SSM::Parameter::Value<SecureString>
    NoEcho: 'true'
    Default: /environment/default/database_password
    Description: The database admin account password

This throws an error:

An error occurred (ValidationError) when calling the CreateStack operation: Template format error: Unrecognized parameter type: SecureString

However, if I refer to this parameter as String instead of SecureString it throws a different error:

An error occurred (ValidationError) when calling the CreateStack operation: Parameters [/environment/default/database_password] referenced by template have types not supported by CloudFormation.

I did try using '{{resolve:ssm-secure:parameter-name:version}}' and it works for database configuration:

MasterUsername: !Ref DatabaseUsername
MasterUserPassword: '{{resolve:ssm-secure:/environment/default/database_password:1}}'

However, I'm using AWS Fargate docker containers where I'm supplying these values as Environment variables:

Environment:
  - Name: DATABASE_HOSTNAME
    Value: !Ref DatabaseHostname
  - Name: DATABASE_USERNAME
     Value: !Ref DatabaseUsername
  - Name: DATABASE_PASSWORD
    Value: '{{resolve:ssm-secure:/environment/default/database_password:1}}'

This throws an error:

An error occurred (ValidationError) when calling the CreateStack operation: SSM Secure reference is not supported in: [AWS::ECS::TaskDefinition/Properties/ContainerDefinitions/Environment]

Unable to use secure strings in my implementation. Is there any workaround to this problem? AWS announced support for SecureString last year, but unable to find the documentation. All I found was to use resolve which only works in some cases.

References:

1

2


Solution 1:

CloudFormation does not support SecureString as template parameter type. You can confirm it in the documentation below, let me quote it.

In addition, AWS CloudFormation does not support defining template parameters as SecureString Systems Manager parameter types. However, you can specify Secure Strings as parameter values for certain resources by using dynamic parameter patterns.

Reference: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#aws-ssm-parameter-types

As you mention you "could" solve it using dynamic parameter patterns, but only a limited amount of resources supports it. ECS and Fargate does not.

Reference: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html

Maybe you can address it using Secrets Manager, instead you set the password as environment variable for you container, your application get the password in runtime from Secrets Manager, this also improves your security, the password will not be in clear text inside the container.

Below you can see one example of this solution, it is not for container, but the "way of work" is the same using environment variable and Secrets Manager.

Reference: https://aws.amazon.com/blogs/security/how-to-securely-provide-database-credentials-to-lambda-functions-by-using-aws-secrets-manager/

Solution 2:

The AWS Secrets Manager can be used to obtain secrets for CloudFormation templates, even where they are not things such as database passwords.

Here is a link to the documentation: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-secretsmanager

There are 3 parts to a Secrets Manager secret:

  • The Secret's Name e.g. PROD_DB_PASSWORD
  • The Secret's Key e.g. DB_PASSWORD
  • And the actual Secret Value

You would then resolve the above secret in your CloudFormation template using:

'{{resolve:secretsmanager:PROD_DB_PASSWORD:SecretString:DB_PASSWORD}}'