Skip to content

binxio/cfn-mysql-user-provider

Repository files navigation

cfn-mysql-user-provider

Although CloudFormation is very good in creating MySQL database servers with Amazon RDS, the mundane task of creating users and database is not supported. This custom MySQL user provider automates the provisioning of MySQL users and databases.

How does it work?

It is quite easy: you specify a CloudFormation resource of the Custom::MySQLUser, as follows:

  KongUser:
    Type: Custom::MySQLUser
    DependsOn: KongPassword
    Properties:
      User: kong
      PasswordParameterName: /MySQL/kong/PGPASSWORD
      WithDatabase: true
      DeletionPolicy: Retain 
      Database:                   # the server to create the new user or database in
        Host: MySQL
        Port: 3306
        DBName: root
        User: root
        PasswordParameterName: /MySQL/root/PGPASSWORD                # put your root password is in the parameter store
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxioio-cfn-mysql-user-provider-vpc-${AppVPC}'

   KongPassword:
    Type: Custom::Secret
    Properties:
      Name: /MySQL/kong/PGPASSWORD
      KeyAlias: alias/aws/ssm
      Alphabet: _&`'~-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
      Length: 30
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider'

After the deployment, the MySQL user 'kong' has been created together with a matching database 'kong'. The password for the root database user has been obtained by querying the Parameter /MySQL/root/PGPASSWORD. If you just want to create a user with which you can login to the MySQL database server, without a database, specify WithDatabase as false.

The DeletionPolicy by default is Retain. This means that the login to the database is disabled. If you specify drop, it will be dropped and your data will be lost.

Installation

To install this Custom Resource, type:

export VPC_ID=$(aws ec2  --output text --query 'Vpcs[?IsDefault].VpcId' describe-vpcs)
export SUBNET_ID=$(aws ec2 --output text --query 'Subnets[0].SubnetId' \
			describe-subnets --filters Name=vpc-id,Values=$VPC_ID)
export SG_ID=$(aws ec2 --output text --query 'SecurityGroups[*].GroupId' \
			describe-security-groups --group-names default  --filters Name=vpc-id,Values=$VPC_ID)

aws cloudformation create-stack \
	--capabilities CAPABILITY_IAM \
	--stack-name cfn-mysql-user-provider \
	--template-body file://cloudformation/cfn-resource-provider.yaml  \
	--parameters \
	            ParameterKey=VPC,ParameterValue=$VPC_ID \
	            ParameterKey=Subnets,ParameterValue=$SUBNET_ID \
                    ParameterKey=SecurityGroup,ParameterValue=$SG_ID

aws cloudformation wait stack-create-complete  --stack-name cfn-mysql-user-provider 

Note that this uses the default VPC, subnet and security group. As the Lambda functions needs to connect to the database. You will need to install this custom resource provider for each vpc that you want to be able to create database users.

This CloudFormation template will use our pre-packaged provider from 463637877380.dkr.ecr.eu-central-1.amazonaws.com/xebia/cfn-mysql-user-provider:2.0.0.

If you have not done so, please install the secret provider too.

cd ..
git clone https https://github.com/binxio/cfn-secret-provider.git 
cd cfn-secret-provider
aws cloudformation create-stack \
	--capabilities CAPABILITY_IAM \
	--stack-name cfn-secret-provider \
	--template-body file://cloudformation/cfn-custom-resource-provider.yaml
aws cloudformation wait stack-create-complete  --stack-name cfn-secret-provider 

Demo

To install the simple sample of the Custom Resource, type:

aws cloudformation create-stack --stack-name cfn-mysql-user-provider-demo \
	--template-body file://cloudformation/demo-stack.yaml
aws cloudformation wait stack-create-complete  --stack-name cfn-mysql-user-provider-demo

It will create a MySQL database too, so it is quite time consuming...

Conclusion

With this solution MySQL users and databases can be provisioned just like the RDS instance, while keeping the passwords safely stored in the AWS Parameter Store.