I updated my secret in AWS Secrets Manager, but the dynamic reference didn't update during my AWS CloudFormation stack update.
Short description
When you update a secret in Secrets Manager, CloudFormation doesn't automatically detect the value of the secret that you changed. When you change the dynamic reference during a stack update, CloudFormation retrieves only the value of the dynamic reference.
After you update the secret in Secrets Manager, you must update the CloudFormation stack, and specify the VersionId in the dynamic reference string. It's a best practice to specify the VersionId so that CloudFormation retrieves the updated version of the secret. You can also add a timestamp parameter to your CloudFormation template to force updates on resources.
Resolution
Update with VersionID
Note: If you receive errors when you run AWS Command Line Interface (AWS CLI) commands, then see Troubleshoot AWS CLI errors. Also, make sure that you're using the most recent AWS CLI version.
Complete the following steps:
-
Dynamically reference the Secrets Manager secret in your CloudFormation template.
In the following example, the CloudFormation template dynamically references a Secrets Manager secret with the mysecret secret-id and {"MyKey":"MyValue"} secret-string:
Resources:
SG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: '{{resolve:secretsmanager:mysecret:SecretString:MyKey}}'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
CidrIp: 0.0.0.0/0
Note: The preceding dynamic reference resolves to MyValue for the GroupDescription property.
-
To update the secret in Secrets Manager, run the update-secret AWS CLI command, and then specify the secret-string.
In the example scenario, the secret-string is {"MyKey":"NewValue"}.
Note: The VersionId doesn't appear on the AWS Management Console. If you used the Console to update your secret, then run the get-secret-value AWS CLI command to retrieve the VersionId.
-
Note the VersionId from the output:
$ aws secretsmanager update-secret --secret-id mysecret --secret-string {\"MyKey\":\"NewValue\"}{
"ARN": "arn:aws:secretsmanager:us-east-1:############:secret:mysecret-ABCDeF",
"Name": "mysecret",
"VersionId": "ab01234c-5d67-89ef-01gh-2ijk345l6m78"
}
Note: The VersionId "ab01234c-5d67-89ef-01gh-2ijk345l6m78" from the preceding output doesn't automatically apply to the dynamic reference in the CloudFormation stack.
-
Update the stack, and specify the VersionId in the dynamic reference string:
Resources:
SG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: '{{resolve:secretsmanager:mysecret:SecretString:MyKey::ab01234c-5d67-89ef-01gh-2ijk345l6m78}}'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
CidrIp: 0.0.0.0/0
Note: In the preceding example template, the :: before "ab01234c-5d67-89ef-01gh-2ijk345l6m78" is the correct syntax. Keep this section of the dynamic reference string blank because you don't need to specify the version stage.
Use a timestamp to force updates
You can also add a timestamp parameter to your CloudFormation template to force updates on resources. Modify a property that allows nondisruptive updates, such as tags or environment variables.
For example, you can add a DeployTimestamp parameter to your CloudFormation template:
Parameters:
DeployTimestamp:
Type: String
Resources:
Function:
Type: AWS::Lambda::Function
Properties:
Environment:
Variables:
SECRET_KEY: !Sub '{{resolve:secretsmanager:${Secret}:SecretString:KEY}}'
SECRET_KEY_UPDATED: !Ref DeployTimestamp
When you update the stack, specify the current date and time for DeployTimestamp to initiate the resource update. Use either the Console or AWS CLI to manually enter the details:
aws cloudformation deploy --parameter-overrides "DeployTimestamp=$(date)"
Note: This method works only with resources that support tags or have properties that allow for nondisruptive updates. If the resource type doesn't support either of these, then use the VersionId to update.