自动执行密钥创建 AWS CloudFormation - AWS Secrets Manager
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

自动执行密钥创建 AWS CloudFormation

使用AWS CloudFormation 模板,您可以在您的 AWS 云基础设施。

您可以使用 AWS CloudFormation 自动创建您的云基础设施。您可以使用 JSON 或 YAML 创建模板以定义项目所需的资源。然后,AWS CloudFormation 处理模板并构建定义的资源。这使您能够在需要时轻松地重新创建基础设施的新副本。例如,您可以复制测试基础设施来创建公有版本。您还可以轻松将基础设施作为简单的文本文件共享,从而使其他人无需手动干预即可复制资源。

您可以使用 CloudFormer 将现有资源集的所有详细信息捕获到 AWS CloudFormation 模板。

Secrets Manager 提供了以下资源类型,以便您能够创建密钥作为 AWS CloudFormation 模板的一部分。有关在 AWS CloudFormation 模板中配置每种资源类型的详细信息,请选择资源类型名称以链接到 AWS CloudFormation 用户指南

  • AWS::SecretsManager::Secret – 创建密钥并将其存储在 Secrets Manager 中。您可以指定一个密码,或者让 Secrets Manager 为您生成一个密码。您还可以创建一个空密钥,并以后使用 SecretString. 参数更新该密钥。

  • AWS::SecretsManager::ResourcePolicy – 创建基于资源的策略并将其附加到指定密钥。基于资源的策略控制谁可以对密钥执行操作。

  • AWS::SecretsManager::RotationSchedule – 配置密钥以使用指定的 Lambda 轮换函数执行自动定期轮换。

  • AWS::SecretsManager::SecretTargetAttachment – 在创建密钥后,如果在创建服务或数据库时引用该密钥以访问凭证,该资源类型将返回并完成密钥配置。Secrets Manager 为密钥配置使轮换正常工作所需的服务或数据库详细信息。例如,对于 Amazon RDS 数据库实例,Secrets Manager 将连接详细信息和数据库引擎类型作为条目添加到密钥的 SecureString 属性中。

Examples

以下示例模板将创建密钥和 Amazon RDS MySQL 使用密钥中的凭证作为主用户和密码的数据库实例。该密钥附加了基于资源的策略,以指定密钥的访问权限。该模板还创建 Lambda 轮换函数并将密钥配置为每 30 天自动轮换一次。

注意

JSON 规范不支持注释。有关注释,请参阅此页面上后面的 YAML 版本。

注意

如果部署 Aurora PostgreSQL 数据库中,您必须创建一个用户名,而不是 admin管理 是保留的关键字,您不能使用该用户名创建数据库。

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": 16, "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": { "AutomaticallyAfterDays": 30 } } } } }

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 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 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 to make api calls to Secrets Manager SecretsManagerVPCEndpoint: Type: AWS::EC2::VPCEndpoint Properties: SubnetIds: - Ref: TestSubnet01 - Ref: TestSubnet02 SecurityGroupIds: - !GetAtt TestVPC.DefaultSecurityGroup VpcEndpointType: 'Interface' ServiceName: !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: 16 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: !Sub '{{resolve:secretsmanager:${MyRDSInstanceRotationSecret}::username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${MyRDSInstanceRotationSecret}::password}}' BackupRetentionPeriod: 0 VPCSecurityGroups: - !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 #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: !GetAtt TestVPC.DefaultSecurityGroup VpcSubnetIds: Fn::Join: - "," - - Ref: TestSubnet01 - Ref: TestSubnet02 RotationRules: AutomaticallyAfterDays: 30