Last year, I wrote a blog about generating secrets in your CloudFormation template and storing them in the Parameter Store. This works when the secret is ours to choose. But what if you are given a secret? For instance an API key or password to be used for authentication at a third party? With the latest feature of the Custom Secret Provider, we allow you to specify an Encrypted secret which will be decrypted before it is stored in the Parameter store.
How does it work?
It is quite easy: you specify the encrypted value in your CloudFormation Custom::Secret resource as EncryptedContent
:
Resources:
ApiKey:
Type: Custom::Secret
Properties:
Name: /datadog/api-key
EncryptedContent: AQICAHgefwksukJYA7L2AkPMZLGjZsGxHbvY9AoVs55dcju1AwEZui/8lNbnGAhv63Wh0heUAAAA3zCB3AYJKoZIhvcNAQcGoIHOMIHLAgEAMIHFBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDOXKKVZ4ft75/oZ2TQIBEICBlzf5j1M3w6OH+iphx59kFLnNoKb+u1RCLfIqEitrt6VGu13/jDlnDcPE2DfkZFkW3fnmNn5OXfgt1L9j4XYdIQTEwexorNqUr5pUtMfS9YX8yL9DbArH+XBv/OQPSj8VsuWRcwFP5EwZKB9O4X3l1pZlPafp2Y/ndWXgC1o6YgfplnmjufoUUTy8wi4P5glbwnqGP/iyc7g=
ReturnSecret: true
RefreshOnUpdate: true
ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider'
The value should be encrypted with the KMS key alias/cmk/cfn-secrets
for the provider to be able to decrypt it.
After the deployment, the API key can be found in the EC Parameter Store with the name /datadog/api-key
as type SecureString. The value is available to you in clear text. If you need to access the secret in your cloudformation module, you need to specify ReturnSecret
and reference it as the attribute Secret
.
DATADOG_API_KEY: !GetAtt 'ApiKey.Secret'
Installation
To install this Custom Resource, type:
git checkout https://github.com/binxio/cfn-secret-provider
cd cfn-secret-provider
aws cloudformation create-stack
--capabilities CAPABILITY_IAM
--stack-name cfn-secret-provider
--template-body
file://cloudformation/cfn-custom-resource-provider.json
aws cloudformation wait stack-create-complete
--stack-name cfn-secret-provider
This CloudFormation template will use our pre-packaged provider from s3://binxio-public/lambdas/cfn-secret-provider-0.13.0.zip
This custom provider is only allowed to decrypt values from the key with the alias alias/cmk/cfn-secrets
created together with the provider. If
you wish to use different keys, add Decrypt permissions to the Lamdba Policy.
Encrypting values
After the CloudFormation provider is deployed, you can encrypt values by using the 4 line python utility encrypt-secret
.
$ ./encrypt-secret my-secret-api-key
Demo
To install the simple sample of the Custom Resource, type:
API_KEY=replace-me-with-your-key
aws cloudformation create-stack
--stack-name cfn-secret-provider-demo
--template-body file://cloudformation/demo-stack.json
--parameters ParameterKey=ApiKey,ParameterValue=$(./encrypt-secret $API_KEY)
aws cloudformation wait stack-create-complete
--stack-name cfn-secret-provider-demo
Of course in this case the secret is passed in as a parameter, as it depends on the key.
to validate that your key was stored in the parameter store,type:
aws ssm get-parameter --name /cfn-secret-provider-demo-api-key --with-decryption
Conclusion
By using the Encrypted content option of the CloudFormation Secret provider, you can
specify given secrets in CloudFormation and deploy them safely to the SSM parameter store.
Got to here? You probably like deploying private key pairs and deploying ACM certificates with CloudFormation.