Two Authentication Methods for RDS Proxy – Password / IAM

TOC

Two Authentication Methods for RDS Proxy

The following page shows how to access RDS from Lambda through RDS Proxy.

あわせて読みたい
Connect to RDS from Lambda in VPC via RDS Proxy 【Connect to RDS from Lambda in VPC via RDS Proxy】 Consider a configuration where Lambda is deployed in a VPC and connects to RDS.When accessing RDS from La...

In the above page, we chose password authentication when connecting from Lambda to RDS Proxy.

Once again, the following is a summary of the authentication flow when using RDS Proxy.

Diagram of the flow of RDS Proxy Authentication.

Two methods are available for clients to connect to the RDS Proxy.
The first is password authentication. The first is password authentication, similar to a typical RDB connection.
The second is IAM authentication, which is an IAM policy-based method for specifying which DB users can connect.

Regardless of which authentication method is selected, the connection between RDS Proxy and RDS will be authenticated using the Secret Manager secret (user name and password).

In this article, we will compare the two authentication methods.

Environment

Diagram of two authentication methods for RDS Proxy(Password/IAM)

The basic structure is the same as in the previous page.
The difference is that we are creating two RDS Proxies for two authentications and preparing a Lambda function to use them.

The following is a brief description of the behavior of the configuration we are creating.
Create a table to store date/time data in a DB instance.
When an HTTP request arrives at the API Gateway, the back-end Lambda is called to retrieve the current date and time.
The acquired date/time data is stored in the DB instance via RDS Proxy.
In addition, all data stored in the DB instance is retrieved and returned as an HTTP response.

CloudFormation Template Files

The above configuration is built using CloudFormation.
The CloudFormation template is located at the following URL

https://github.com/awstut-an-r/awstut-fa/tree/main/039

Explanation of key points of the template files

The basic configuration is the same as the following page.

あわせて読みたい
Connect to RDS from Lambda in VPC via RDS Proxy 【Connect to RDS from Lambda in VPC via RDS Proxy】 Consider a configuration where Lambda is deployed in a VPC and connects to RDS.When accessing RDS from La...

This page focuses on the RDS Proxy and the contents related to connecting to DB instances through the RDS Proxy.

Two authentication methods for RDS Proxy

RDS Proxy with password authentication

Let’s start with password authentication.

Resources:
  DBProxy1:
    Type: AWS::RDS::DBProxy
    Properties:
      Auth:
        - IAMAuth: DISABLED
          AuthScheme: SECRETS
          SecretArn: !Ref Secret
      DBProxyName: !Sub "${Prefix}-DBProxy-01"
      EngineFamily: !Ref DBProxyEngineFamily
      IdleClientTimeout: !Ref IdleClientTimeout
      RequireTLS: false
      RoleArn: !GetAtt DBProxyRole.Arn
      VpcSecurityGroupIds:
        - !Ref DBProxySecurityGroup
      VpcSubnetIds:
        - !Ref DBSubnet1
        - !Ref DBSubnet2
Code language: YAML (yaml)

There are two points.

The first is the Auth property.
Since IAM authentication is not used here, set the IAMAuth property to “DISABLED”.

The second is the RequireTLS property.
In the case of password authentication, there is no need to enable TLS, so set it to “FALSE”.

RDS Proxy for IAM Authentication

Next, check IAM authentication.

Resources:
  DBProxy2:
    Type: AWS::RDS::DBProxy
    Properties:
      Auth:
        - IAMAuth: REQUIRED
          AuthScheme: SECRETS
          SecretArn: !Ref Secret
      DBProxyName: !Sub "${Prefix}-DBProxy-02"
      EngineFamily: !Ref DBProxyEngineFamily
      IdleClientTimeout: !Ref IdleClientTimeout
      RequireTLS: true
      RoleArn: !GetAtt DBProxyRole.Arn
      VpcSecurityGroupIds:
        - !Ref DBProxySecurityGroup
      VpcSubnetIds:
        - !Ref DBSubnet1
        - !Ref DBSubnet2
Code language: YAML (yaml)

Check the two previous points.

In the first point, the IAMAuth property in the Auth property should be set to “REQUIRED”.
This will enable IAM authentication.

The RequireTLS property in the second point should be set to “true”.
This is a requirement for IAM authentication.

Make sure that you use Transport Layer Security (TLS)/Secure Sockets Layer (SSL) when connecting to a proxy using IAM authentication.

Connecting to a proxy using IAM authentication

Lambda functions connecting to the RDS Proxy

Lambda Layer

The two Lambda functions each use mysql-connector-python to connect to a MySQL type DB instance.
This time, the same package is prepared as a Lambda layer and referenced by the two functions.

Resources:
  LambdaLayer:
    Type: AWS::Lambda::LayerVersion
    Properties:
      CompatibleRuntimes:
        - !Ref Runtime
      Content:
        S3Bucket: !Ref CodeS3Bucket
        S3Key: !Ref CodeS3Key3
      Description: !Ref Prefix
      LayerName: !Ref Prefix
Code language: YAML (yaml)

The following command creates a ZIP file for the Lambda layer and uploads it to the S3 bucket

$ pip3 install mysql-connector-python -t ./python

$ zip -r layer.zip python

$ aws s3 cp layer.zip s3://[s3-bucket-name]/
Code language: Bash (bash)

For more information on Lambda layers, please refer to the following page

あわせて読みたい
Create Lambda layer using CFN 【Creating Lambda Layer using CloudFormation】 This page reviews how to create a Lambda layer in CloudFormation. Lambda layers provide a convenient way to pa...

Lambda functions for password authentication

Check the Lambda function to connect with password authentication.

Resources:
  Function1:
    Type: AWS::Lambda::Function
    Properties:
      Environment:
        Variables:
          DB_ENDPOINT_PORT: !Ref MySQLPort
          DB_NAME: !Ref DBName
          DB_PASSWORD: !Ref DBMasterUserPassword
          DB_PROXY_ENDPOINT_ADDRESS: !Ref DBProxyEndpointAddress1
          DB_TABLENAME: !Ref DBTableName
          DB_USER: !Ref DBMasterUsername
          REGION: !Ref AWS::Region
      Code:
        S3Bucket: !Ref CodeS3Bucket
        S3Key: !Ref CodeS3Key1
      FunctionName: !Sub "${Prefix}-function-01"
      Handler: !Ref Handler
      Layers:
        - !Ref LambdaLayer
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole1.Arn
      Timeout: !Ref Timeout
      VpcConfig:
        SecurityGroupIds:
          - !Ref FunctionSecurityGroup
        SubnetIds:
          - !Ref FunctionSubnet
Code language: YAML (yaml)

The point is the environment variables.
The Environment property allows you to define environment variables that can be used within a function.
A particularly important variable is the password (DB_PASSWORD) for connecting to the DB instance.
This function is for password authentication.

The IAM role for this function is as follows

Resources:
  FunctionRole1:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
Code language: YAML (yaml)

No special configuration is required.
Only the AWS management policy prepared for Lambda is specified.

Check the contents of the function.
In particular, we will focus on the part that creates the MySQL connection object.

import mysql.connector
import os

db_endpoint_port = os.environ['DB_ENDPOINT_PORT']
db_name = os.environ['DB_NAME']
db_password = os.environ['DB_PASSWORD']
db_proxy_endpoint_address = os.environ['DB_PROXY_ENDPOINT_ADDRESS']
db_tablename = os.environ['DB_TABLENAME']
db_user = os.environ['DB_USER']
region = os.environ['REGION']


def lambda_handler(event, context):
    conn = mysql.connector.connect(
        host=db_proxy_endpoint_address,
        port=db_endpoint_port,
        user=db_user,
        password=db_password,
        database=db_name
        )
Code language: Python (python)

Use mysql-connector-python (mysql.connector) provided in the Lambda layer.
This is password authentication, so in addition to the RDS Proxy endpoint, etc. to which you are connecting, you must specify a password.

Lambda function for IAM authentication

Check the Lambda function to connect with IAM authentication.

Resources:
  Function2:
    Type: AWS::Lambda::Function
    Properties:
      Environment:
        Variables:
          DB_ENDPOINT_PORT: !Ref MySQLPort
          DB_NAME: !Ref DBName
          #DB_PASSWORD: !Ref DBMasterUserPassword
          DB_PROXY_ENDPOINT_ADDRESS: !Ref DBProxyEndpointAddress2
          DB_TABLENAME: !Ref DBTableName
          DB_USER: !Ref DBMasterUsername
          REGION: !Ref AWS::Region
          SSLCERTIFICATE: AmazonRootCA1.pem
      Code:
        S3Bucket: !Ref CodeS3Bucket
        S3Key: !Ref CodeS3Key2
      FunctionName: !Sub "${Prefix}-function-02"
      Handler: !Ref Handler
      Layers:
        - !Ref LambdaLayer
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole2.Arn
      Timeout: !Ref Timeout
      VpcConfig:
        SecurityGroupIds:
          - !Ref FunctionSecurityGroup
        SubnetIds:
          - !Ref FunctionSubnet
Code language: YAML (yaml)

The difference from the previous function for password authentication is the environment variable to be defined.
Since this is IAM authentication, the password is not needed, so it is commented out.
As described later, the file name of the certificate to be included in the deployment package for the Lambda function is also defined as a variable.

The IAM role for this function is as follows

Resources:
  FunctionRole2:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
      Policies:
        - PolicyName: AllowRDSDBConnectPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - rds-db:connect
                Resource:
                  - !Sub "arn:aws:rds-db:${AWS::Region}:${AWS::AccountId}:dbuser:${DBProxyId2}/${DBMasterUsername}"
Code language: YAML (yaml)

In addition to the AWS management policies discussed earlier, define an inline policy.
The content of this policy is to allow the “rds-db:connect” action for the DB user specified at DB instance creation.

This policy was defined by referring to the following page

https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html

Check the contents of the function.
In particular, we will focus on the creation of the MySQL connection object.

import mysql.connector
import os

db_endpoint_port = os.environ['DB_ENDPOINT_PORT']
db_name = os.environ['DB_NAME']
#db_password = os.environ['DB_PASSWORD']
db_proxy_endpoint_address = os.environ['DB_PROXY_ENDPOINT_ADDRESS']
db_tablename = os.environ['DB_TABLENAME']
db_user = os.environ['DB_USER']
region = os.environ['REGION']
ssl_certificate = os.environ['SSLCERTIFICATE']

os.environ['LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN'] = '1'

client = boto3.client('rds', region_name=region)

def lambda_handler(event, context):
    token = client.generate_db_auth_token(
        DBHostname=db_proxy_endpoint_address,
        Port=db_endpoint_port,
        DBUsername=db_user,
        Region=region)

    conn = mysql.connector.connect(
        host=db_proxy_endpoint_address,
        user=db_user,
        password=token,
        port=db_endpoint_port,
        database=db_name,
        ssl_ca=ssl_certificate)
Code language: Python (python)

Refer to the following page to implement object creation during IAM authentication.

https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.Connecting.Python.html

There are two points.
The first is to create a temporary token and use it as the password, rather than setting the password directly.
The token is created with client.generate_db_auth_token.

The second point is the specification of the certificate.
When connecting to a DB instance with IAM authentication, a certificate must be specified.
This certificate can be downloaded from AWS.

For the .pem file to use, download all root CA PEMs from Amazon Trust Services and place them into a single .pem file.

RDS Proxy concepts and terminology

The following command is an example of downloading a certificate

$ curl -OL https://www.amazontrust.com/repository/AmazonRootCA1.pem
Code language: Bash (bash)

When creating the package for the Lambda function, zip and deploy this certificate (AmazonRootCA1.pem) as well.

Architecting

Using CloudFormation, build this environment and check the actual behavior.

Create CloudFormation stacks and check resources in stacks

Create a CloudFormation stack.
For information on how to create stacks and check each stack, please refer to the following page

あわせて読みたい
CloudFormation’s nested stack 【How to build an environment with a nested CloudFormation stack】 Examine nested stacks in CloudFormation. CloudFormation allows you to nest stacks. Nested ...

After checking the resources in each stack, information on the main resources created this time is as follows

  • API Gateway endpoints: https://6ug0w6jg5b.execute-api.ap-northeast-1.amazonaws.com

The resource creation status is also checked from the AWS Management Console.
Check the items related to RDS Proxy authentication.

RDS Proxy 1 authentication method.
RDS Proxy 2 authentication method.

The RDS Proxy is configured for password authentication and IAM authentication, respectively.

Confirmation of Operation

Now that everything is ready, access the API Gateway.

First, check the operation of the Lambda function that connects with password authentication.
/func1 is the URL of this function.

The Result of Lambda function 1.

The response is returned normally.
We have confirmed that we can connect with password authentication.

Next, check the operation of the Lambda function that connects with IAM authentication.
/func2 is the URL of this function.

The Result of Lambda function 2.

The response was returned normally.
We have confirmed that we can connect with IAM authentication.

Summary

We confirmed two authentication methods when connecting from Lambda to DB instance via RDS Proxy.

TOC