Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

node-mysql2, AWS.RDS.signer, & connection pooling

I am using the node-mysql2 library in combination with AWS.RDS.signer.

I have the following function, which creates a connection pool for reusing connections:

const createPool = () => new Promise((resolve, reject) => {
    signer.getAuthToken({
        region: '...',
        hostname: '...',
        port: '...',
        username: '...'
    }, (err, token) => {
        if (err) reject(err)
        const pool = mysql.createPool({
            host: '...',
            port: '...',
            user: '...',
            database: '...',
            password: token,
            ssl: 'Amazon RDS'
            authSwitchHandler: (data, cb) => {
                if (data.pluginName === 'mysql_clear_password') cb(null, Buffer.from(token + '\0'))
            }
        })
        resolve(pool)
    })
})

It works great... for awhile. Then I suddenly start getting this error:

Error: Access denied for user '...'@'...' (using password: YES)

So, what I think is happening, is that the token returned by the aws signer is only valid for a short time, and cannot be used to continuously re-establish connections in a pool.

There is no way to configure the ttl of the rds token using the aws sdk, that I can see. So the only other option I can think of, is to completely end and recreate the pool at a certain fixed interval.

I am wondering if there is anyone out there who may have wrestled with this, and who may have some insight into the best way to solve this problem? Is there a better way to use the rds signer in combination with connection pools?

like image 208
user1031947 Avatar asked Sep 18 '25 07:09

user1031947


1 Answers

For node-mysql2 version >= 2.0.0

mysql.createPool({
    ...,
    ssl: 'Amazon RDS',
    authPlugins: {
        mysql_clear_password: () => () =>
            signer.getAuthToken({
                region: '...',
                hostname: '...',
                port: '...',
                username: '...'
            })
    }
});

For node-mysql2 version < 2.0.0

mysql.createPool({
    ...,
    ssl: 'Amazon RDS',
    authSwitchHandler: (data, cb) => {
        if (data.pluginName === 'mysql_clear_password') {
            signer.getAuthToken({
                    region: '...',
                    hostname: '...',
                    port: '...',
                    username: '...'
                },
                (err, token) => {
                    if (err) {
                        cb(err);
                    } else {
                        cb(null, Buffer.from(token + '\0'));
                    }
                }
            );
        } else {
            cb(new Error(`Authentication method ${data.pluginName} is not supported`));
        }
    }
});

See also https://github.com/sidorares/node-mysql2/issues/1017

like image 163
David Krásný Avatar answered Sep 19 '25 21:09

David Krásný