Can't connect to RDS via AWS.RDS.Signer

Viewed 1482

I'm trying to connect to my MySQL RDS from a Lambda via AWS.RDS.Signer with the following code and fake credentials:

1  const DB_REGION = 'ap-southeast-2a'
2  const DB_HOST = 'dbinstance.ddtev8utygt.ap-southeast-2.rds.amazonaws.com'
3  const DB_PORT = 3306
4  const DB_USER = 'anyuser'
5  const DB_NAME = 'anydb'
6
7  const signerOptions = {
8    region: DB_REGION,
9    hostname: DB_HOST,
10   port: DB_PORT,
11   username: DB_USER
12 }
13
14 const signer = new AWS.RDS.Signer(signerOptions)
15 const token = await signer.getAuthToken()
16 
17 const config = {
18   host: DB_HOST,
19   user: DB_USER,
20   password: token, // "Password123"
21   database: DB_NAME,
22   ssl: 'Amazon RDS',
23   authPlugins: {
24     mysql_clear_password: () => () => token
25   }
26 }

but I always get this error

"Access denied for user 'anyuser'@'172.14.1.12' (using password: NO)"

I'm not entirely sure if that is needed for the AWS.RDS.Signer but I selected this option of my database:

Password and IAM database authentication
Authenticates using the database password and user credentials through AWS IAM users and roles. 

NOTE: If I swap the password from token to "Password123" on line 20 I can successfully connect to my RDS.

Am I missing something here or does AWS.RDS.Signer only work with RDS Proxy?

By the way: the getAuthToken function gives me something like that (token truncated)

"dbinstance.ddtev8utygt.apsoutheast2.rds.amazonaws.com:3306/Action=connect&DBUser=anyuser&&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAU7VGXF6UCWYZCFEG%2F20210318%2Fap-southeast-2a%2Frds-db%2Faws4_request&X-Amz-Date=20210318T105145Z&X-Amz-Expires=900&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEAsaDmFwLXNvdXRoZWFzdC0yIkgwRgIhAKg8ibwNJ4E3hSOuq7HtDFvqHxmTlpOUk3I6EH2%2B9VdOV3RQ%2F03xiVdvjhEBkHqEXHQ%3D&X-Amz-Signature=749d931f74873e6c2c0d4fec94f0743f42efd5aa95ca0ac0f05c4bef30e3bd4d&X-Amz-SignedHeaders=host"

1 Answers

I finally can connect to my RDS via Lamdba using IAM (aka AWS.RDS.Signer)

So what was the problem?

  • Short story:

I used the wrong region in my Policy and in the props for the AWS.RDS.Signer.

I assumed that the Availability zone (ap-southeast-2a) equals the region, but that's not true. The correct region is actually described when the AWS command line creds get created. To find out the region invoke cat ~/.aws/config from the terminal. My default region was actually region=ap-southeast-2.

  • Long story:

When I started with AWS.RDS.Signer I followed the instructions here When it came to extracting the DB info for the Policy, I used this command

aws rds describe-db-instances --db-instance-identifier <MY INSTANCE NAME> --query "DBInstances[*].DbiResourceId" --region ap-southeast-2a

but I got this error Could not connect to the endpoint URL: "https://rds.ap-southeast-2a.amazonaws.com/"

After a bit of Googling, I realised that the region is not right. That gave me a hint to change the region in the policy and in the code of my Lambda function.

{
   "Version": "2012-10-17",
   "Statement": [
       {
           "Effect": "Allow",
           "Action": [
               "rds-db:connect"
           ],
           "Resource": [
               "arn:aws:rds-db:<my-region>:<my-account-id>:dbuser:<my-db-resource-id>/<my-db-username>"
           ]
       }
   ]
}

Then I created an extra user (ssluser) in the DB to connect with the AWS.RDS.Signer token

CREATE USER 'ssluser' IDENTIFIED WITH AWSAuthenticationPlugin as 'RDS';
GRANT ALL PRIVILEGES ON <MY DB NAME>.* TO 'ssluser'@'%';
GRANT USAGE ON <MY DB NAME>.* TO 'ssluser'@'%' REQUIRE SSL;

The next step was to add the above policy to the EC2 instance, ssh into the instance, install the MySQL client yum install mysql and try to connect to the instance using the token

mysql --host=dbinstance.chteb5kjtggo.ap-southeast-2.rds.amazonaws.com --port=3306 --ssl-ca=rds-combined-ca-bundle.pem --enable-cleartext-plugin --user=ssluser --password=`aws rds generate-db-auth-token --hostname dbinstance.chteb5kjtggo.ap-southeast-2.rds.amazonaws.com --port 3306 --region ap-southeast-2 --username ssluser`

After successfully connect to the RDS without providing a password I only had to attach the policy to my Lambda and change the username and region in my Lambda code to

1  const DB_REGION = 'ap-southeast-2'
2  const DB_HOST = 'dbinstance.ddtev8utygt.ap-southeast-2.rds.amazonaws.com'
3  const DB_PORT = 3306
4  const DB_USER = 'ssluser'
5  const DB_NAME = 'anydb'

I hope that will help someone in the future.

Related