AWS has Fully Configured and Ready-to-Use Rotation Support for some supported RDS engines, including Amazon Aurora (Serverless also?)
I'm trying to setup the password rotation in my CloudFormation template using AWS::SecretsManager::RotationSchedule
(note that this is not a fully functional template, only an illustration):
DBCluster:
Type: AWS::RDS::DBCluster
Properties:
Engine : aurora
EngineMode : serverless
EngineVersion : 5.6.10a
Secret:
Type: AWS::SecretsManager::Secret
Properties:
GenerateSecretString:
SecretStringTemplate: '{"username": "admin"}'
GenerateStringKey: password
PasswordLength: 20
ExcludeCharacters: '"@/\'
SecretTargetAttachment:
Type: AWS::SecretsManager::SecretTargetAttachment
Properties:
SecretId: !Ref Secret
TargetId: !Ref DBCluster
TargetType: AWS::RDS::DBCluster
SecretRotation:
Type: AWS::SecretsManager::RotationSchedule
Properties:
SecretId: !Ref UserAdminSecret
RotationLambdaARN: <ARN_GET_FROM_SERVERLESS_APPLICATION_REPOSITORY>
RotationRules:
AutomaticallyAfterDays: 1
But the AWS Lambda rotation function fails with the following message:
"Database engine must be set to 'mysql' in order to use this rotation lambda": KeyError
Looks like Aurora Serverless is not supported by the AWS Lambda rotation function provided by AWS.
Is there an easy way to setup Aurora Serverless secret rotation using existing Lambda rotation templates?
Any example available to write my own rotation function for Aurora Serverless?
PS: This question is kind of related to Creating an Aurora Serverless Cluster from cloudformation?
The RotationSchedule resource has a dependency on the SecretTargetAttachment resource. The attachment resource updates your secret-string value to contain connection information such as db engine, port and endpoint.
Unfortunately, there is no way for CloudFormation to know about this implicit dependency between the two resources. You need to put a DependsOn on the RotationSchedule resource with the attachment resource's logical id.
See the RotationSchedule resource in this example - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-secretsmanager-rotationschedule.html#aws-resource-secretsmanager-rotationschedule--examples
I wasn't using serverless, but I got the same exact error.
"Database engine must be set to 'mysql' in order to use this rotation lambda": KeyError
For me, the problem was that I needed to provide subnets and a security group to the rotation lambda.
A sketch of the CloudFormation template would look like (notice the parameters passed into the lambda):
DBSecrets:
Type: AWS::SecretsManager::Secret
Properties:
GenerateSecretString:
SecretStringTemplate: '{"username": "XXXXXXXXXX"}'
GenerateStringKey: password
PasswordLength: 24
ExcludeCharacters: '"@/\'
DBSecretsRDSAttachment:
Type: AWS::SecretsManager::SecretTargetAttachment
Properties:
SecretId: !Ref DBSecrets
TargetId: !Ref RDSDatabase
TargetType: AWS::RDS::DBInstance
SecretRotationSchedule:
Type: AWS::SecretsManager::RotationSchedule
DependsOn: DBSecretsRDSAttachment
Properties:
SecretId: !Ref DBSecrets
RotationLambdaARN: !GetAtt MySQLRotationLambda.Outputs.RotationLambdaARN
RotationRules:
AutomaticallyAfterDays: 30
MySQLRotationLambda:
Type: AWS::Serverless::Application
Properties:
Location:
ApplicationId: <ARN_GET_FROM_SERVERLESS_APPLICATION_REPOSITORY>
SemanticVersion: 1.1.0
Parameters:
endpoint: !Sub 'https://secretsmanager.${AWS::Region}.amazonaws.com'
functionName: <Function Name>
vpcSubnetIds: <Comma delimited List of VPC subnet IDs>
vpcSecurityGroupIds: <Comma delimited List of VPC security grouop IDs>
RDSDatabase:
Type: AWS::RDS::DBInstance
Properties:
MasterUsername: !Sub '{{resolve:secretsmanager:${DBSecrets}::username}}'
MasterUserPassword: !Sub '{{resolve:secretsmanager:${DBSecrets}::password}}'
Engine: mysql
DBSubnetGroupName: <Your Subnet Group>
VPCSecurityGroups: <Your Security Group>
The rotation Lambda goes through the following steps:
It fails to login with pending and current secret, then fails with this error when trying the previous secret. The pending and current secret are valid, the Lambda just can't make a connection to the database. The previous secret is the secret that you initially provide in the CloudFormation template above.
{
"username": "XXXXXXXXXX",
"password": "XXXXXXXXXX"
}
The AWS::SecretsManager::SecretTargetAttachment
changes it to the proper format (for RDS MySQL Single User):
{
"engine": "mysql",
"host": "<required: instance host name/resolvable DNS name>",
"username": "<required: username>",
"password": "<required: password>",
"dbname": "<optional: database name. If not specified, defaults to None>",
"port": "<optional: TCP port number. If not specified, defaults to 3306>"
}
The rotation Lambda nested stack has more parameters that you can pass in, just look at its template in the CloudFormation dashboard.
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