Criar um segredo do Secrets Manager com alternância automática e uma instância de banco de dados do MySQL do Amazon RDS com o AWS CloudFormation - AWS Secrets Manager

Criar um segredo do Secrets Manager com alternância automática e uma instância de banco de dados do MySQL do Amazon RDS com o AWS CloudFormation

Este exemplo cria um segredo e uma instância de banco de dados do MySQL do Amazon RDS usando as credenciais no segredo como usuário e senha. O Secrets Manager gera uma senha com 32 caracteres. O modelo também cria uma função de alternância do Lambda a partir de Modelos de função de alternância e configura o segredo para alternar automaticamente entre às 8h e 10h UTC do primeiro dia de cada mês. Como uma prática recomendada de segurança, a instância de banco de dados está em uma Amazon VPC.

Para ver um exemplo sem alternância automática, consulte Criar um segredo com credenciais do Amazon RDS.

Este exemplo usa os seguintes recursos do CloudFormation para o Secrets Manager:

Para obter informações sobre como criar recursos com o AWS CloudFormation, consulte Saiba mais sobre noções básicas de modelo no Guia do usuário do AWS CloudFormation.

JSON

{ "Transform": "AWS::SecretsManager-2020-07-23", "Description": "This is an example template to demonstrate CloudFormation resources for Secrets Manager", "Resources": { "TestVPC": { "Type": "AWS::EC2::VPC", "Properties": { "CidrBlock": "10.0.0.0/16", "EnableDnsHostnames": true, "EnableDnsSupport": true } }, "TestSubnet01": { "Type": "AWS::EC2::Subnet", "Properties": { "CidrBlock": "10.0.96.0/19", "AvailabilityZone": { "Fn::Select": [ "0", { "Fn::GetAZs": { "Ref": "AWS::Region" } } ] }, "VpcId": { "Ref": "TestVPC" } } }, "TestSubnet02": { "Type": "AWS::EC2::Subnet", "Properties": { "CidrBlock": "10.0.128.0/19", "AvailabilityZone": { "Fn::Select": [ "1", { "Fn::GetAZs": { "Ref": "AWS::Region" } } ] }, "VpcId": { "Ref": "TestVPC" } } }, "SecretsManagerVPCEndpoint": { "Type": "AWS::EC2::VPCEndpoint", "Properties": { "SubnetIds": [ { "Ref": "TestSubnet01" }, { "Ref": "TestSubnet02" } ], "SecurityGroupIds": [ { "Fn::GetAtt": [ "TestVPC", "DefaultSecurityGroup" ] } ], "VpcEndpointType": "Interface", "ServiceName": { "Fn::Sub": "com.amazonaws.${AWS::Region}.secretsmanager" }, "PrivateDnsEnabled": true, "VpcId": { "Ref": "TestVPC" } } }, "MyRDSInstanceRotationSecret": { "Type": "AWS::SecretsManager::Secret", "Properties": { "Description": "This is my rds instance secret", "GenerateSecretString": { "SecretStringTemplate": "{\"username\": \"admin\"}", "GenerateStringKey": "password", "PasswordLength": 32, "ExcludeCharacters": "/@\"'\\" }, "Tags": [ { "Key": "AppName", "Value": "MyApp" } ] } }, "MyDBInstance": { "Type": "AWS::RDS::DBInstance", "Properties": { "AllocatedStorage": 20, "DBInstanceClass": "db.t2.micro", "Engine": "mysql", "DBSubnetGroupName": { "Ref": "MyDBSubnetGroup" }, "MasterUsername": { "Fn::Sub": "{{resolve:secretsmanager:${MyRDSInstanceRotationSecret}::username}}" }, "MasterUserPassword": { "Fn::Sub": "{{resolve:secretsmanager:${MyRDSInstanceRotationSecret}::password}}" }, "BackupRetentionPeriod": 0, "VPCSecurityGroups": [ { "Fn::GetAtt": [ "TestVPC", "DefaultSecurityGroup" ] } ] } }, "MyDBSubnetGroup": { "Type": "AWS::RDS::DBSubnetGroup", "Properties": { "DBSubnetGroupDescription": "Test Group", "SubnetIds": [ { "Ref": "TestSubnet01" }, { "Ref": "TestSubnet02" } ] } }, "SecretRDSInstanceAttachment": { "Type": "AWS::SecretsManager::SecretTargetAttachment", "Properties": { "SecretId": { "Ref": "MyRDSInstanceRotationSecret" }, "TargetId": { "Ref": "MyDBInstance" }, "TargetType": "AWS::RDS::DBInstance" } }, "MySecretRotationSchedule": { "Type": "AWS::SecretsManager::RotationSchedule", "DependsOn": "SecretRDSInstanceAttachment", "Properties": { "SecretId": { "Ref": "MyRDSInstanceRotationSecret" }, "HostedRotationLambda": { "RotationType": "MySQLSingleUser", "RotationLambdaName": "SecretsManagerRotation", "VpcSecurityGroupIds": { "Fn::GetAtt": [ "TestVPC", "DefaultSecurityGroup" ] }, "VpcSubnetIds": { "Fn::Join": [ ",", [ { "Ref": "TestSubnet01" }, { "Ref": "TestSubnet02" } ] ] } }, "RotationRules": { "Duration": 2h, "ScheduleExpression": "cron(0 8 1 * ? *)" } } } } }

YAML

--- Transform: AWS::SecretsManager-2020-07-23 Description: This is an example template to demonstrate CloudFormation resources for Secrets Manager Resources: #This is the VPC that the rotation Lambda function and the RDS instance will be placed in TestVPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsHostnames: true EnableDnsSupport: true # Subnet that the rotation Lambda function and the RDS instance will be placed in TestSubnet01: Type: AWS::EC2::Subnet Properties: CidrBlock: 10.0.96.0/19 AvailabilityZone: Fn::Select: - '0' - Fn::GetAZs: Ref: AWS::Region VpcId: Ref: TestVPC TestSubnet02: Type: AWS::EC2::Subnet Properties: CidrBlock: 10.0.128.0/19 AvailabilityZone: Fn::Select: - '1' - Fn::GetAZs: Ref: AWS::Region VpcId: Ref: TestVPC #VPC endpoint that will enable the rotation Lambda function to make api calls to Secrets Manager SecretsManagerVPCEndpoint: Type: AWS::EC2::VPCEndpoint Properties: SubnetIds: - Ref: TestSubnet01 - Ref: TestSubnet02 SecurityGroupIds: - Fn::GetAtt: - TestVPC - DefaultSecurityGroup VpcEndpointType: Interface ServiceName: Fn::Sub: com.amazonaws.${AWS::Region}.secretsmanager PrivateDnsEnabled: true VpcId: Ref: TestVPC #This is a Secret resource with a randomly generated password in its SecretString JSON. MyRDSInstanceRotationSecret: Type: AWS::SecretsManager::Secret Properties: Description: This is my rds instance secret GenerateSecretString: SecretStringTemplate: '{"username": "admin"}' GenerateStringKey: password PasswordLength: 32 ExcludeCharacters: "/@\"'\\" Tags: - Key: AppName Value: MyApp #This is an RDS instance resource. Its master username and password use dynamic references to resolve values from #SecretsManager. The dynamic reference guarantees that CloudFormation will not log or persist the resolved value #We sub the Secret resource's logical id in order to construct the dynamic reference, since the Secret's name is being #generated by CloudFormation MyDBInstance: Type: AWS::RDS::DBInstance Properties: AllocatedStorage: 20 DBInstanceClass: db.t2.micro Engine: mysql DBSubnetGroupName: Ref: MyDBSubnetGroup MasterUsername: Fn::Sub: "{{resolve:secretsmanager:${MyRDSInstanceRotationSecret}::username}}" MasterUserPassword: Fn::Sub: "{{resolve:secretsmanager:${MyRDSInstanceRotationSecret}::password}}" BackupRetentionPeriod: 0 VPCSecurityGroups: - Fn::GetAtt: - TestVPC - DefaultSecurityGroup #Database subnet group for the RDS instance MyDBSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: DBSubnetGroupDescription: Test Group SubnetIds: - Ref: TestSubnet01 - Ref: TestSubnet02 #This is a SecretTargetAttachment resource which updates the referenced Secret resource with properties about #the referenced RDS instance SecretRDSInstanceAttachment: Type: AWS::SecretsManager::SecretTargetAttachment Properties: SecretId: Ref: MyRDSInstanceRotationSecret TargetId: Ref: MyDBInstance TargetType: AWS::RDS::DBInstance #This is a RotationSchedule resource. It configures rotation of password for the referenced secret using a rotation lambda function #The first rotation happens at resource creation time, with subsequent rotations scheduled according to the rotation rules #We explicitly depend on the SecretTargetAttachment resource being created to ensure that the secret contains all the #information necessary for rotation to succeed MySecretRotationSchedule: Type: AWS::SecretsManager::RotationSchedule DependsOn: SecretRDSInstanceAttachment Properties: SecretId: Ref: MyRDSInstanceRotationSecret HostedRotationLambda: RotationType: MySQLSingleUser RotationLambdaName: SecretsManagerRotation VpcSecurityGroupIds: Fn::GetAtt: - TestVPC - DefaultSecurityGroup VpcSubnetIds: Fn::Join: - "," - - Ref: TestSubnet01 - Ref: TestSubnet02 RotationRules: Duration: 2h ScheduleExpression: 'cron(0 8 1 * ? *)'