Deploying secrets with AWS CloudFormation

One of the biggest pains we encounter in creating immutable infrastructures with CloudFormation, is dealing with secrets. Secrets
must be passed into the CloudFormation templates to make them different per environment. These secrets
must be given out to the development teams, so that they can do something useful with them. Before you know it,
your secrets are compromised.


With this Custom CloudFormation Resource we put an end to that. Secrets are generated as a CloudFormation Resource and
stored in the EC2 parameter store. This means that we do not have to store the secrets anywhere unsafe and applications
can get access to the secrets in a controlled manner.

How does it work?

It is quite easy: you specify a CloudFormation resource of the Custom::Secret, as follows:

<span style="font-weight:bold">Resources</span>:<span style="color:#bbb">
</span><span style="color:#bbb"></span><span style="color:#bbb">  </span><span style="font-weight:bold">DBPassword</span>:<span style="color:#bbb">
</span><span style="color:#bbb"></span><span style="color:#bbb">    </span><span style="font-weight:bold">Type</span>:<span style="color:#bbb"> </span>Custom::Secret<span style="color:#bbb">
</span><span style="color:#bbb">    </span><span style="font-weight:bold">Properties</span>:<span style="color:#bbb">
</span><span style="color:#bbb"></span><span style="color:#bbb">      </span><span style="font-weight:bold">Name</span>:<span style="color:#bbb"> </span>/postgres/root/PGPASSWORD<span style="color:#bbb">
</span><span style="color:#bbb">      </span><span style="font-weight:bold">KeyAlias</span>:<span style="color:#bbb"> </span>alias/aws/ssm<span style="color:#bbb">
</span><span style="color:#bbb">      </span><span style="font-weight:bold">Alphabet</span>:<span style="color:#bbb"> </span>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789<span style="color:#bbb">
</span><span style="color:#bbb">      </span><span style="font-weight:bold">Length</span>:<span style="color:#bbb"> </span><span style="color:#099">30</span><span style="color:#bbb">
</span><span style="color:#bbb">      </span><span style="font-weight:bold">ReturnSecret</span>:<span style="color:#bbb"> </span><span style="font-weight:bold">true</span><span style="color:#bbb">
</span><span style="color:#bbb">      </span><span style="font-weight:bold">Version</span>:<span style="color:#bbb"> </span>v1<span style="color:#bbb">
</span><span style="color:#bbb">      </span><span style="font-weight:bold">ServiceToken</span>:<span style="color:#bbb"> </span>!Sub<span style="color:#bbb"> </span><span style="color:#b84">'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider'</span><span style="color:#bbb">
</span><span style="color:#bbb">
</span>

After the deployment, a 30 character random string can be found in the EC Parameter Store with the name /postgres/root/PGPASSWORD. If you need to access
the secret in your cloudformation module, you need to specify ReturnSecret and reference it as the attribute Secret.

<span style="color:#bbb">     </span><span style="font-weight:bold">MasterUserPassword</span>:<span style="color:#bbb"> </span>!GetAtt<span style="color:#bbb"> </span><span style="color:#b84">'DBPassword.Secret'</span><span style="color:#bbb">
</span>

Installation

To install this Custom Resource, type:

git clone https://github.com/binxio/cfn-secret-provider.git
<span style="color:#999">cd</span> cfn-secret-provider

aws cloudformation create-stack <span style="color:#b84">\
</span><span style="color:#b84"></span> --capabilities CAPABILITY_IAM <span style="color:#b84">\
</span><span style="color:#b84"></span> --stack-name cfn-secret-provider <span style="color:#b84">\
</span><span style="color:#b84"></span> --template-body <span style="color:#b84">\
</span><span style="color:#b84"></span> file://cloudformation/cfn-custom-resource-provider.yaml 

aws cloudformation <span style="color:#999">wait</span> stack-create-complete  <span style="color:#b84">\
</span><span style="color:#b84"></span> --stack-name cfn-secret-provider 

This CloudFormation template will use our pre-packaged provider from

s3://binxio-public/lambdas/cfn-secret-provider-latest.zip

Demo

To install the simple sample of the Custom Resource, type:

aws cloudformation create-stack <span style="color:#b84">\
</span><span style="color:#b84"></span> --capabilities CAPABILITY_NAMED_IAM <span style="color:#b84">\
</span><span style="color:#b84"></span> --stack-name cfn-secret-provider-demo <span style="color:#b84">\
</span><span style="color:#b84"></span> --template-body file://cloudformation/demo-stack.yaml

aws cloudformation <span style="color:#999">wait</span> stack-create-complete  <span style="color:#b84">\
</span><span style="color:#b84"></span> --stack-name cfn-secret-provider-demo

to validate the result, type:

aws ssm get-parameter --name /postgres/root/PGPASSWORD  --with-decryption

Conclusion

By using the CloudFormation Secret provider:

  • secrets are generated per environment.
  • secrets can be updated.
  • always stored encrypted in the parameter store .
  • where access to the secrets is audited and controlled!

If you have a 3rd party secret like an API key, checkout deploying given secrets.
If you want to deploy a private key pair, checkout deploying private key pairs.
In addition we automated the deployment of ACM certificates with CloudFormation.

Mark van Holsteijn is a senior software systems architect, and CTO of binx.io. He is passionate about removing waste in the software delivery process and keeping things clear and simple.
Share this article: Tweet this post / Post on LinkedIn