Last active
November 18, 2021 21:16
-
-
Save pgressa/2340592195722081ee41601a0439274c to your computer and use it in GitHub Desktop.
cloudformation for rds and autorotate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
AWSTemplateFormatVersion: "2010-09-09" | |
Transform: AWS::SecretsManager-2020-07-23 | |
Description: Deploys an RDS instance | |
Metadata: | |
AWS::CloudFormation::Interface: | |
ParameterGroups: | |
- Label: | |
default: Basic configuration | |
Parameters: | |
- DBName | |
- DBInstanceClass | |
- DBAllocatedStorage | |
- CidrIp | |
ParameterLabels: | |
DBName: | |
default: Database name | |
DBInstanceClass: | |
default: Database instance class | |
DBAllocatedStorage: | |
default: The size of the database (GiB) | |
CidrIp: | |
default: CIDR block for the ingress security group | |
Parameters: | |
DBName: | |
Default: dbname | |
Description: Database name | |
Type: String | |
MinLength: '1' | |
MaxLength: '64' | |
AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' | |
ConstraintDescription: Must begin with a letter and contain only alphanumeric characters. | |
DBInstanceClass: | |
Default: db.m5.large | |
Description: DB instance class | |
Type: String | |
ConstraintDescription: Must select a valid DB instance type. | |
DBAllocatedStorage: | |
Default: '50' | |
Description: The size of the database (GiB) | |
Type: Number | |
MinValue: '5' | |
MaxValue: '1024' | |
ConstraintDescription: must be between 20 and 65536 GiB. | |
CidrIp: | |
AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(0|1[6-9]|2[0-8]))$ | |
ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16–28 | |
Default: 10.0.0.0/16 | |
Description: CIDR block for the ingress security group. | |
Type: String | |
Resources: | |
# Inspiration https://docs.aws.amazon.com/secretsmanager/latest/userguide/integrating_cloudformation.html | |
# RDS VPC | |
RdsVpc: | |
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 | |
RdsSubnet01: | |
Type: AWS::EC2::Subnet | |
Properties: | |
CidrBlock: 10.0.96.0/19 | |
AvailabilityZone: | |
Fn::Select: | |
- '0' | |
- Fn::GetAZs: { Ref: 'AWS::Region' } | |
VpcId: | |
Ref: RdsVpc | |
RdsSubnet02: | |
Type: AWS::EC2::Subnet | |
Properties: | |
CidrBlock: 10.0.128.0/19 | |
AvailabilityZone: | |
Fn::Select: | |
- '1' | |
- Fn::GetAZs: {Ref: 'AWS::Region'} | |
VpcId: | |
Ref: RdsVpc | |
# VPC endpoint that will enable the rotation Lambda function to make api calls to Secrets Manager | |
SecretsManagerVPCEndpoint: | |
Type: AWS::EC2::VPCEndpoint | |
Properties: | |
SubnetIds: | |
- Ref: RdsSubnet01 | |
- Ref: RdsSubnet02 | |
SecurityGroupIds: | |
- !GetAtt RdsVpc.DefaultSecurityGroup | |
VpcEndpointType: 'Interface' | |
ServiceName: !Sub "com.amazonaws.${AWS::Region}.secretsmanager" | |
PrivateDnsEnabled: true | |
VpcId: | |
Ref: RdsVpc | |
# This is a Secret resource with a randomly generated password in its SecretString JSON. | |
RDSInstanceRotationSecret: | |
Type: AWS::SecretsManager::Secret | |
Properties: | |
GenerateSecretString: | |
SecretStringTemplate: '{"username": "admin"}' | |
GenerateStringKey: 'password' | |
PasswordLength: 16 | |
ExcludeCharacters: '"@/\' | |
# 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 | |
DBInstance: | |
Type: AWS::RDS::DBInstance | |
Properties: | |
AllocatedStorage: !Ref DBAllocatedStorage | |
DBInstanceClass: !Ref DBInstanceClass | |
Engine: mysql | |
DBSubnetGroupName: | |
Ref: DBSubnetGroup | |
MasterUsername: !Sub '{{resolve:secretsmanager:${RDSInstanceRotationSecret}::username}}' | |
MasterUserPassword: !Sub '{{resolve:secretsmanager:${RDSInstanceRotationSecret}::password}}' | |
BackupRetentionPeriod: 0 | |
VPCSecurityGroups: | |
- !GetAtt RdsVpc.DefaultSecurityGroup | |
- Ref: EksSecurityGroup | |
DBName: !Ref DBName | |
# Database subnet group for the RDS instance | |
DBSubnetGroup: | |
Type: AWS::RDS::DBSubnetGroup | |
Properties: | |
DBSubnetGroupDescription: "DB Subnet group" | |
SubnetIds: | |
- Ref: RdsSubnet01 | |
- Ref: RdsSubnet02 | |
# 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 RDSInstanceRotationSecret | |
TargetId: !Ref DBInstance | |
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 | |
SecretRotationSchedule: | |
Type: AWS::SecretsManager::RotationSchedule | |
DependsOn: SecretRDSInstanceAttachment | |
Properties: | |
SecretId: !Ref RDSInstanceRotationSecret | |
HostedRotationLambda: | |
RotationType: MySQLSingleUser | |
RotationLambdaName: SecretsManagerRotation | |
VpcSecurityGroupIds: !GetAtt RdsVpc.DefaultSecurityGroup | |
VpcSubnetIds: | |
Fn::Join: | |
- "," | |
- - Ref: RdsSubnet01 | |
- Ref: RdsSubnet02 | |
RotationRules: | |
AutomaticallyAfterDays: 2 | |
EksSecurityGroup: | |
Type: AWS::EC2::SecurityGroup | |
Properties: | |
GroupDescription: Open database for access | |
VpcId: !Ref RdsVpc | |
SecurityGroupIngress: | |
- IpProtocol: tcp | |
FromPort: '3306' | |
ToPort: '3306' | |
CidrIp: | |
Ref: CidrIp | |
Outputs: | |
DbPort: | |
Value: !GetAtt DBInstance.Endpoint.Port | |
DbAddress: | |
Value: !GetAtt DBInstance.Endpoint.Address |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment