Search code examples
aws-cloudformationamazon-rdsaws-cloudformation-custom-resource

Create RDS DB User CloudFormation


As CloudFormation does not natively support creating a DB User for an RDS Database, I am looking for ways to do this via CustomResource. However, even if I write a CustomResource backed by a Lambda function, I do not see an RDS API endpoint that would allow me to add a user to a database instance.

Could anyone suggest potential ways to create a DB User for an Aurora Cluster backed by Postgres 10 database engine?


Solution

  • I do not see an RDS API endpoint that would allow me to add a user to a database instance.

    Usually you would set your custom resource to trigger after RDS is created. Thus, you can pass the RDS endpoint url to the lambda using, for example, function environment variables.

    Practically DependsOn attribute on your custom resource could be used to ensure that the custom resource triggers after the RDS is successfully created. Not really needed if you pass the RDS url though environmental variables.

    Update code with example lambda which uses pymysql:

         
      MyLambdaFunction:
        Type: AWS::Lambda::Function
        Properties:
          Handler: index.lambda_handler
          Role: !Ref ExecRoleArn
          Runtime: python3.7
          Environment:
            Variables: 
              DB_HOSTNAME: !Ref DbHostname
              DB_USER: !Ref DbMasterUsername
              DB_PASSWORD: !Ref DbMasterPassword
              DB_NAME: !Ref DbName
          VpcConfig:
            SecurityGroupIds: [!Ref SecurityGroupId]
            SubnetIds: !Ref SubnetIds
          Code:
            ZipFile: |
                import base64
                import json
                import os
                import logging
                import random
                import sys
    
    
                import pymysql
                import boto3
    
                rds_host  = os.environ['DB_HOSTNAME']
                rds_user = os.environ['DB_USER']
                rds_password = os.environ['DB_PASSWORD']
                rds_dbname = os.environ['DB_NAME']
    
                logger = logging.getLogger()
                logger.setLevel(logging.INFO)
    
                try:
                    
                    conn = pymysql.connect(rds_host, 
                                           user=rds_user,
                                           passwd=rds_password, 
                                           db=rds_dbname, 
                                           connect_timeout=5)
                except:
                    logger.error("ERROR: Unexpected error: Could not connect to MySql instance.")
                    sys.exit()          
    
                def lambda_handler(event, context):
    
                    print(json.dumps(event))
    
                    with conn.cursor() as cur:
    
                        cur.execute("create table if not exists Employee (EmpID  int NOT NULL auto_increment, Name varchar(255) NOT NULL, PRIMARY KEY (EmpID))")
    
                        conn.commit()
    
        
                    return {
                        'statusCode': 200,
                        'body': ""
                    }     
    
    
          Timeout: 60 # 
          MemorySize: 128
          Layers: 
            - arn:aws:lambda:us-east-1:113088814899:layer:Klayers-python37-PyMySQL:1