Rod
Rod

Reputation: 15475

AWS Lambda and RDS working example (need it to work with Sequelize)

Here's a working example of AWS Lambda and MySQL, but I'd like it to work with Sequelize. How do I initialize Sequelize to work with AWS Lambda? I have the authenticated IAM role working too.

https://dzone.com/articles/passwordless-database-authentication-for-aws-lambd

'use strict';
const mysql = require('mysql2');
const AWS = require('aws-sdk');
// TODO use the details of your database connection
const region = 'eu-west-1';
const dbPort = 3306;
const dbUsername = 'lambda'; // the name of the database user you created in step 2
const dbName = 'lambda_test'; // the name of the database your database user is granted access to
const dbEndpoint = 'lambdatest-cluster-1.cluster-c8o7oze6xoxs.eu-west-1.rds.amazonaws.com';
module.exports.handler = (event, context, cb) => {
  var signer = new AWS.RDS.Signer();
  signer.getAuthToken({ // uses the IAM role access keys to create an authentication token
    region: region,
    hostname: dbEndpoint,
    port: dbPort,
    username: dbUsername
  }, function(err, token) {
    if (err) {
      console.log(`could not get auth token: ${err}`);
      cb(err);
    } else {
      var connection = mysql.createConnection({
        host: dbEndpoint,
        port: dbPort,
        user: dbUsername,
        password: token,
        database: dbName,
        ssl: 'Amazon RDS',
        authSwitchHandler: function (data, cb) { // modifies the authentication handler
          if (data.pluginName === 'mysql_clear_password') { // authentication token is sent in clear text but connection uses SSL encryption
            cb(null, Buffer.from(token + '\0'));
          }
        }
      });
      connection.connect();
      // TODO replace with your SQL query
      connection.query('SELECT * FROM lambda_test.test', function (err, results, fields) {
        connection.end();
        if (err) {
          console.log(`could not execute query: ${err}`);
          cb(err);
        } else {
          cb(undefined, results);
        }
      });
    }
  });
};

Upvotes: 1

Views: 2825

Answers (2)

Dillon Bourne
Dillon Bourne

Reputation: 41

Instead of using mysql.createConnection() and use your RDS Signer token:

var sequelize = require('sequelize')
const Sequelize = new sequelize(
        process.env.database_name,
        process.env.databse_user,
        token,
        {
            dialect: 'mysql',
            dialectOptions: {
                ssl: 'Amazon RDS',
                authPlugins: { // authSwitchHandler is deprecated
                    mysql_clear_password: () => () => {
                        return token
                    }
                }
            },
            host: process.env.db_proxy_endpoint,
            port: process.env.db_port,
            pool: {
                min: 0, //default
                max: 5, // default
                idle: 3600000
            },
            define: {
                charset: 'utf8mb4'
            }
        }
// then return your models (defined in separate files usually) 
await Sequelize.authenticate() // this just does a SELECT 1+1 as result;
await Sequelize.sync() // DO NOT use this in production, this tries to create tables defined by your models. Consider using sequelize migrations instead of using sync()

Also it's a good idea to keep your database connection parameters in a config file so no one can see them. (process.env)

Upvotes: 3

Marlom
Marlom

Reputation: 688

We are working with Sequelize and Lambda, but you will need to reserve more resources, in our case we need at least 1GB to run a lambda with Sequelize. Without it, just with mysql2 it runs just with 128MB.

But if you really wanna use Sequelize just replace your createConnection for something like what you will find in sequelize doc

Probably you will use the context.callbackWaitsForEmptyEventLoop=true because you may have some issues when you call the callback function and you get nothing because your Event Loop probably will never be empty.

Upvotes: 0

Related Questions