In the following (abbreviated CloudFormation template), I am trying to configure an AWS Lambda function to get a value from AWS Secrets Manager injected into its environment:
Resources:
Function:
Type: AWS::Serverless::Function
Properties:
Environment:
Variables:
SECRET_KEY: !Sub '{{resolve:secretsmanager:${Secret}:SecretString:KEY}}'
Secret:
Type: AWS::SecretsManager::Secret
Properties:
Name: 'very-secret-thing'
SecretString: '{"KEY":"dummy"}'
When creating a stack using this template, everything comes up as expected. I then go and change the value of the secret outside of CloudFormation, as I would not really want the secret checked into source control. This is totally possible, and the documentation implies, that the secret's value will not be touched subsequent CloudFormation stack updates, as long as I avoid changing the dummy value for SecretString
in the template.
So, after setting the actual secret in the AWS Console, I need to trigger a redeploy of the Lambda function, so that the new secret value will be resolved by CloudFormation and set in the function's environment. How do I do that?
Executing aws cloudformation deploy
fails with the message: No changes to deploy.
I suspect CloudFormation is comparing the "raw" version of the template with what was deployed last, without first resolving the references to Secrets Manager. Is that the case? And is there some trick to force earlier dereferencing?
Footnote: I am well aware that using Secrets Manager this way will cause the secret value to be visible in the AWS Lambda Console, and that getting the value from Secrets Manager at runtime would be the more secure approach. That just happens to be out-of-scope for what I am hoping to do.
You can artificially change something else on the AWS::Serverless::Function
resource to force it to update when you do your deployment.
Say, for example, a timestamp:
Parameters:
DeployTimestamp: { Type: String }
Resources:
Function:
Type: AWS::Serverless::Function
Properties:
Environment:
Variables:
SECRET_KEY: !Sub '{{resolve:secretsmanager:${Secret}:SecretString:KEY}}'
SECRET_KEY_UPDATED: !Ref DeployTimestamp
Assuming you do your deployment from a script, then you'd do something like aws cloudformation deploy --parameter-overrides "DeployTimestamp=$(date)"
to change the value each time.
The downside to this, of course, is that the function will update every deployment, even if the secret hasn't updated. If that bothers you, you could get fancier and inject aws secretsmanager describe-secret --query LastChangedDate
as a parameter instead of the current time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With