Skip to main content

No project description provided

Project description

django-mysql-rds

A Django db backend for connecting to RDS MySQL instances using SSL db auth tokens.

Use

I'd recommend understanding what you're doing and why before dropping this in, but chances are that you have a DATABASES dict that looks something like:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': DBNAME,
        'USER': USER,
        'PASSWORD': aws_client.generate_db_auth_token(HOST, PORT, USER),
        'HOST': HOST,
        'PORT': PORT,
        'OPTIONS': {
            'ssl': {
                'ca': 'certs/rds-cert.pem'
            }
        }
    }
}

And you've discovered that after ~15 minutes you make a request and receive Access Denied for user@instance because the password has expired.

This package allows you to generate the password at connection time by passing a callable instead:

def generate_pw():
    return aws_client.generate_db_auth_token(HOST, PORT, USER)

DATABASES = {
    'default': {
        'ENGINE': 'mysql_rds.backend',
        'NAME': DBNAME,
        'USER': USER,
        'PASSWORD': generate_pw,
        'HOST': HOST,
        'PORT': PORT,
        'CONN_MAX_AGE': 900,
        'OPTIONS': {
            'ssl': {
                'ca': 'certs/rds-cert.pem'
            }
        }
    }
}

I recommend setting a CONN_MAX_AGE of 900 as the generated auth token expires after 900 seconds. This ensures that connections requiring a refresh recreated. You can pass any function as the password and it will be evaluated at connection time. For testing locally if you cannot connect to directly to RDS you can do something like:

def generate_pw():
    return 'password'

Installation

$ pip install django-mysql-rds

or

$ git clone git@github.com:cramshaw/django-mysql-rds.git

Why?

When I searched for a way to connect to an AWS RDS MySQL instance using SSL inside Django, I was unable to find anything that could handle the fact that the db auth token generated by AWS would expire every 15 minutes.

The problem is that when anything in the settings module changes, Django needs to reload. This isn't practical in a long running web app. I needed a way for the password to be generated at the time of connection.

How?

On close inspection of the django.db.backends.mysql code, it became clear that the DatabaseWrapper.get_connection_params method takes the settings dict, and transforms it into the kwargs that are passed to mysql.connect. I have subclassed this and extended to recognise if the password passed in is a callable, and if so, to call it and pass on the returned value. This leads to Django receiving a fresh password every time a connection is created.

A very similar thing happens in the DatabaseClient.settings_to_cmd_args which is used for things like dumping and loading data. This has also been subclassed and changed to ensure the password generation method actually runs before attempting to create a run a shell.

Caveats

Whilst this works for me running django==2.2 and should work exactly the same as the built in MySQL backend, there are no guarantees.

I only needed this to work for MySQL. I haven't explored whether RDS does the same for Postgres or other databases, but the same principle ought to apply.

Running Tests

Tests require mysqlclient installed.

$ brew install mysql-client
$ export PATH="/usr/local/opt/mysql-client/bin:$PATH"

Then to run:

$ python -m unittest tests/test*

Packaging

Bump version in setup.py then:

$ rm -rf dist/
$ python3 setup.py sdist bdist_wheel
$ python3 -m twine upload dist/*

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-mysql-rds-1.0.0.tar.gz (9.2 kB view details)

Uploaded Source

Built Distribution

django_mysql_rds-1.0.0-py3-none-any.whl (10.2 kB view details)

Uploaded Python 3

File details

Details for the file django-mysql-rds-1.0.0.tar.gz.

File metadata

  • Download URL: django-mysql-rds-1.0.0.tar.gz
  • Upload date:
  • Size: 9.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.6.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.61.2 CPython/3.9.6

File hashes

Hashes for django-mysql-rds-1.0.0.tar.gz
Algorithm Hash digest
SHA256 252dfe53ae0dd3dc0c333153e0801ba895a124eda0263daf5b5c502bb030a6f3
MD5 93827db415c0ea2c4b0b57af719b94ea
BLAKE2b-256 4fbf340becf3d13c6ede37852a6efd21367a5fd2dceaef9b9d419612c9f8828b

See more details on using hashes here.

File details

Details for the file django_mysql_rds-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: django_mysql_rds-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 10.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.6.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.61.2 CPython/3.9.6

File hashes

Hashes for django_mysql_rds-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1294719a3db02310aeeca438eaf6f8a752783224694d4817e8c179a8fd30f75f
MD5 8656652feb9a25562df04d6eb145cada
BLAKE2b-256 89b4ee5bdf07ad08e2d7404cc13967fea2841456fffbd18e7d51ab9298d4a8a4

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page