April 17th, 2018
How to Provision AWS RDS Instances with CloudFormation Securely
By Pavel Yarema

Relational Database Service (RDS) is an AWS service that is used often in the Amazon Web Services ecosystem. The service manages the database infrastructure but still provides you with customizability of your database. Most of the clients that I interact with use RDS to manage some, if not all, of their relational database needs. However, when provisioning RDS instances through CloudFormation, there is an issue that may arise; the issue can create a security risk if not handled correctly.

Problem

When provisioning an RDS Instance using CloudFormation there are several parameters that need to be supplied in order for the RDS instance to be created properly. One of these parameters is the MasterUserPassword.  However, the value provided for this parameter is a string. Leaving the password in plain text is a serious security vulnerability especially if the CloudFormation template is version-controlled and is accessible by multiple users. Therefore, I decided to build a solution that will mitigate this problem.

Solution

Giving it much thought, I decided not only to explain the solution that will mitigate this problem but also one that will automate it in a CloudFormation template. I created a CloudFormation template that will securely provision a random password and apply it as the RDS master password securely. The solution that I will be describing can be found in our rds-starter-template GitHub repository.

  • First, the CloudFormation template provisions an SSM parameter where the password will be stored.
  • Then, a KMS Key is provisioned that will encrypt the SSM parameter.
  • Next, a Lambda function is provisioned and invoked to generate a strong random password and place the password in the SSM parameter, encrypting it with the provisioned KMS key.
  • Once that is completed, another Lambda function is provisioned and invoked to decrypt the SSM parameter and pass it into the CloudFormation template using a special send function that I customized to ensure that the password is not reflected anywhere in the logs.
  • Finally, the CloudFormation provisions the RDS resource using the parameters specified but references the returned Lambda function value for the MasterUserPassword.

This solution solves a few problems. First, it automates the process of generating a strong RDS instance master password. Secondly, it eliminates the need to store the password in plain text inside configuration files. Thirdly, it provides an opportunity to control access of who can view the password. This is done by allowing (or denying) permissions through IAM to use the KMS key.  If a user has permissions to the key, they would be able to decrypt the SSM parameter value (the password) with the key. Alternately, if a user is denied permission to use the KMS key, they won’t be able to retrieve (decrypt) the SSM parameter value (the password).

 

Conclusion

As I completed developing this solution, I realized that a similar process can be used to create and pass any sensitive information into the CloudFormation template. Though the solution specifically targets the MasterUserPassword property when creating RDS instances, the solution can be easily refactored for other use cases.

If you have further questions regarding AWS RDS or any other AWS services, feel free to schedule a consultation with us (info@1Strategy.com) or email me directly (pavel@new.1strategy.com).