Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conn Configuration for AWS Lambda Python RDS Postgres IAM Authentication

Recently it was create the possibility to access RDS instances with IAM users and roles. I am confused about how to configure a python connection, since I would not use the database authentication data with psycopg2.

Now I am using like this:

conn = psycopg2.connect("dbname='%s' user='%s' host='%s' password='%s'" % (db_name, db_user, db_host, db_pass))

I have not idea how to use IAM credentials to connect my lambda function with IAM auth.

Please help.

like image 844
Gustavo Sooeiro Avatar asked Sep 17 '25 23:09

Gustavo Sooeiro


1 Answers

First, you need to create an IAM policy and a DB user as described here:

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

Then you need to create IAM role for your Lambda function and attach the IAM policy created above to it. Your Lambda function will need to be executed with this role to be able to create a temporary DB password for the DB user.

Finally, you can generate a temporary password for your DB user (created above) within your Lambda using a code snippet like this:

from urllib.parse import quote_plus
import boto3

def get_password(rds_hostname, db_user, aws_region=None, url_encoded=True):
    if (not aws_region):
        aws_region = boto3.session.Session().region_name
        if (not aws_region):
            raise Exception("Error: no aws_region given and the default region is not set!")

    rds_port = 5432
    if (":" in rds_hostname):
        split_hostname = rds_hostname.split(":")
        rds_hostname = split_hostname[0]
        rds_port = int(split_hostname[1])

    rds_client = boto3.client("rds")

    password = rds_client.generate_db_auth_token( Region=aws_region,
                                                  DBHostname=rds_hostname,
                                                  Port=rds_port, 
                                                  DBUsername=db_user)
    if url_encoded:
        return quote_plus( password )
    else:
        return password

Do not assign the the password to a variable. Get a new password on every run, since the password has limited time validity and your Lambda container might not be recycled before it expires...

Finally, create the DB connection string for whatever python package you use (I would suggest some pure Python implementation, such as pg8000) from your RDS hostname, port, username and the temporary password obtained with the function above (<user>:<password>@<hostname>:<port>/<db_name>).

Connecting to the RDS might be a bit tricky. If you don't know how to set up VPC's properly I would suggest you run your Lambda outside of VPC and connect to the RDS over a public IP.

Additionally, you will probably need to enforce SSL connection and possibly include the RDS CA file in your Lambda deployment package. The exact way how to do this depends on what you use to connect (I could only describe how to do this with pymysql and sqlalchemy).

Each of these steps could be described in a tutorial of it's own, but knowing about them should be enough to get you started.

Good luck!

like image 193
grepe Avatar answered Sep 22 '25 21:09

grepe