AWS Secrets Manager: Create and Rotate secrets automatically

Moha Alsouli
5 min readNov 25, 2019

--

Do you want to automate creating secrets to fully secure them away from humans? Or do you have a requirement to rotate database passwords regularly and wonder if you can automate it? It’s all possible with Secrets Manager. Let me take you through it step by step.

As mentioned in my previous article, Security is a top priority at Tigerspike alongside Improving People’s Lives Through Technology.

One of the cool tricks our DevOps team is using to secure and simplify management of our databases credentials on AWS is using AWS Secrets Manager to auto-create and auto-rotate credentials.

Let’s see how easy is using AWS Secrets Manager.
The below examples are snippets of YAML formatted CloudFormation templates.

Create an encrypted username and password

MyRDSSecret:
Type: AWS::SecretsManager::Secret
Properties:
Name: 'ProdDBSecret'
Description: 'Secret with dynamically generated password.'
GenerateSecretString:
RequireEachIncludedType: True
SecretStringTemplate: '{"username": "MyDBAdmin"}'
GenerateStringKey: 'password'
PasswordLength: 25
ExcludePunctuation: True

Voila! The above CloudFormation snippet creates a secret containing a username and password. The username is provided in the template, while the password is auto generated with the properties defined, i.e. 25 characters long, excludes all punctuation marks and must include a mix of lowercase letters, uppercase letters and numbers. Easy.

You can also be more creative with the created secret following your application requirement. For example, you can include punctuation marks and instead exclude certain characters that your database or application do not support such as " quote marks, / slashes or \ backslashes. See Secrets Manager Secret syntax documentation for more.

The created secret will be available for you in Secrets Manager console (if you have the right IAM permissions) but can also be referenced dynamically within your CloudFormation template to create and configure an RDS instance or cluster with it. Read on.

Dynamically configure a database with the created secret

MyRDSInstance:
Type: AWS::RDS::DBInstance
Properties:
AllocatedStorage: 20
DBInstanceClass: db.m5.large
Engine: mysql
MasterUsername: !Join ['', ['{{resolve:secretsmanager:', !Ref MyRDSSecret, ':SecretString:username}}' ]]
MasterUserPassword: !Join ['', ['{{resolve:secretsmanager:', !Ref MyRDSSecret, ':SecretString:password}}' ]]
BackupRetentionPeriod: 14
DBInstanceIdentifier: 'prod-db-with-rotation'
SecretRDSInstanceAttachment:
Type: AWS::SecretsManager::SecretTargetAttachment
Properties:
SecretId: !Ref MyRDSSecret
TargetId: !Ref MyRDSInstance
TargetType: AWS::RDS::DBInstance

The above CloudFormation snippet shows how to create a simple RDS MySQL instance and configure it with the master username and password credentials created by Secrets Manager. The !Join function appends the values to into a single value while the !Ref function is used assuming all resources are in the same template. If the database resource is not in the same template as the secret earlier, you can reference the friendly name of the secret instead such as '{{resolve:secretsmanager:ProdDBSecret:SecretString:password}}'. And once created, the Target Attachment will ensure the final link between the secret and the database is complete. See this doc to learn more on using dynamic references to Secrets Manager Secrets. And see this doc to read more about Secrets Manager Secret Attachment.

At this stage, if you don’t need to rotate your secrets and just wonder how to pass the automated secrets to your apps, jump the next section. Otherwise, continue reading to learn how to rotate secrets and improve the security of your apps.

Regularly rotate the created secret

As password rotation strategies differ between databases, AWS offers multiple rotation Lambda function templates that you can use out of the box or tweak to fit your needs. Take a look at this doc to see the available templates.

For our example, we will use the RDS MySQL Master User rotation function. Here’s how to simply deploy it as a Serverless app:

AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: "This is an AWS Serverless Application Model template for Secret Rotation Lambda"
Resources:
MyRotationServerlessApp:
Type: AWS::Serverless::Application
Properties:
Location:
ApplicationId: 'arn:aws:serverlessrepo:us-east-1:297356227824:applications/SecretsManagerRDSMySQLRotationMultiUser'
SemanticVersion: 1.1.0
Parameters:
endpoint: !Sub 'https://secretsmanager.${AWS::Region}.amazonaws.com'
functionName: SecretsManagerMySQLRotationFunction

The above Serverless Application Model “SAM” template will simply deploy the rotation Lambda function in your account with the IAM role it needs using the AWS application referenced in ApplicationId. See here if you’re not familiar with using or deploying AWS SAM templates.

Once the function is created, you can then use it to rotate your supported secrets. For example, to do so, take a note of the created Lambda function’s ARN and add the below to the CloudFormation template where your secret and secret attachment are:

MySecretRotationSchedule:
Type: AWS::SecretsManager::RotationSchedule
DependsOn: SecretRDSInstanceAttachment
Properties:
SecretId: !Ref MyRDSSecret
RotationLambdaARN: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:SecretsManagerMySQLRotationFunction'
RotationRules:
AutomaticallyAfterDays: 30

Voila! The above snippet will schedule a 30 days rotation for your secret using the rotation function created earlier. See here to learn more about the Rotation Schedule syntax or read here for more about Secrets Rotation.

And just like that, with a few lines of code, we have:

  • Created a Secret consisting of a Username and Password
  • Configured an RDS database instance with the secret
  • Attached the secret to the database to complete the link
  • Created a Secret Rotation Lambda function
  • Used the Secret Rotation Lambda function to schedule a rotation

What’s next?

You should be satisfied by now how we’ve automated the entire process of managing a secret, but you might be wondering how would you configure your app or service to use this secret?!

Well, it’s not that complicated. There are many ways to automate the configuration of your app. The easiest are:

  • Make use of AWS CLI or SDK in your code to retrieve the secrets.
    This is explained in this AWS doc, but you can also see Sample Code in Secrets Manager console when you browse your secrets, which looks like this in the console:
  • Use Environment Variables to pass these secrets to your application.
    Take a look at my earlier blog post which highlights how to pass Environment Variables to an app, otherwise see this AWS doc which explains it in details.

That’s it folks!

Easy and Secure secret management with no human or manual handling needed. See here to learn more about Secrets Manager, or see here to read more on Secrets Rotation and supported services.

--

--