sidorares / node-mysql2

:zap: fast mysqljs/mysql compatible mysql driver for node.js
https://sidorares.github.io/node-mysql2/
MIT License
4.07k stars 619 forks source link

authSwitchHandler not being triggered #771

Open garyrutland opened 6 years ago

garyrutland commented 6 years ago

Hi,

I've been trying to set up IAM authentication for my AWS RDS instance and can't seem to get it working. I believe I have everything correct on the infrastructure side but I keep getting a Access denied error. In the authSwitchHandler function I've added a console.log but it never seems to get triggered.

Is there any reason why it wouldn't happen?

I've put some example code that I'm trying to execute below.

Thanks, Gary

const AWS = require('aws-sdk');
const mysql = require('mysql2/promise');

const signer = new AWS.RDS.Signer({
  region: process.env.REGION,
  hostname: process.env.DB_HOSTNAME,
  port: 3306,
  username: process.env.DB_USERNAME,
});
const token = signer.getAuthToken();

exports.main = async (event, context, callback) => {
  const config = {
    host: process.env.DB_HOSTNAME,
    user: process.env.DB_USERNAME,
    password: token,
    database: process.env.DB_NAME,
    ssl: 'Amazon RDS',
    authSwitchHandler: (data, cb) => {
      console.log('authSwitchHandler', data);
      cb(null, Buffer.from(`${token}\0`));
    },
  };
  console.log('Config', config);

  const connection = await mysql.createConnection(config);
  console.log('Connection', connection);

  return callback(null, {
    statusCode: 200,
    body: true,
  });
};
{
    "errorMessage": "Access denied for user 'user'@'x.x.x.x' (using password: YES)",
    "errorType": "Error",
    "stackTrace": [
        "Object.createConnection (/var/task/node_modules/mysql2/promise.js:31:31)",
        "exports.main (/var/task/src/handler.js:26:34)"
    ]
}
sidorares commented 6 years ago

Hi @garyrutland . Can you post debug log? ( pass debug: true to config)

garyrutland commented 6 years ago

I hope this is enough, annoyingly Cloud Watch doesn't recursively output though.

2018-04-14T07:45:54.173Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    Add command: Connection

2018-04-14T07:45:54.179Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    raw: 0a352e372e32312d6c6f6700090b0000362a1f1a4f556a7400ffff080200ffc1150000000000000000000002710c7208370f0a62087a7e006d7973716c5f6e61746976655f70617373776f726400

2018-04-14T07:45:54.180Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    [object Object]
at Connection.handlePacket (/var/task/node_modules/mysql2/lib/connection.js:472:15)
at PacketParser.onPacket (/var/task/node_modules/mysql2/lib/connection.js:81:16)
at PacketParser.executeStart (/var/task/node_modules/mysql2/lib/packet_parser.js:77:14)
at Socket.<anonymous> (/var/task/node_modules/mysql2/lib/connection.js:89:29)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at Socket.Readable.push (_stream_readable.js:208:10)
at TCP.onread (net.js:607:20)

2018-04-14T07:45:54.180Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    0 undefined ==> Connection#handshakeInit(0,,82)

2018-04-14T07:45:54.213Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    Server hello packet: capability flags:3254779903=(long password, found rows, long flag, connect with db, no schema, compress, odbc, local files, ignore space, protocol 41, interactive, ssl, ignore sigpipe, transactions, reserved, secure connection, multi statements, multi results, ps multi results, plugin auth, connect attrs, plugin auth lenenc client data, can handle expired passwords, session track, deprecate eof, ssl verify server cert, remember options)

2018-04-14T07:45:54.214Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    0 2825 <== Connection#handshakeInit(1,,36)

2018-04-14T07:45:54.214Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    0 2825 <== 20000001cff9aa0000000000e00000000000000000000000000000000000000000000000

2018-04-14T07:45:54.215Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    Upgrading connection to TLS

2018-04-14T07:45:54.260Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    Sending handshake packet: flags:11205071=(long password, found rows, long flag, connect with db, odbc, local files, ignore space, ssl, ignore sigpipe, transactions, reserved, secure connection, multi results, plugin auth, plugin auth lenenc client data, session track)

2018-04-14T07:45:54.261Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    0 2825 <== Connection#handshakeResult(2,,101)

2018-04-14T07:45:54.261Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    0 2825 <== 61000002cff9aa0000000000e000000000000000000000000000000000000000000000006a6f75726e6c65745f6772617068716c001413e749d50f7866526f2eb73fe7a44afff26c3a416d61696e006d7973716c5f6e61746976655f70617373776f726400

2018-04-14T07:45:54.270Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    raw: ff15044163636573732064656e69656420666f722075736572202727402731302e302e322e3230362720287573696e672070617373776f72643a204e4f29

2018-04-14T07:45:54.271Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    [object Object]
at Connection.handlePacket (/var/task/node_modules/mysql2/lib/connection.js:472:15)
at PacketParser.onPacket (/var/task/node_modules/mysql2/lib/connection.js:81:16)
at PacketParser.executeStart (/var/task/node_modules/mysql2/lib/packet_parser.js:77:14)
at TLSSocket.<anonymous> (/var/task/node_modules/mysql2/lib/connection.js:373:31)
at emitOne (events.js:116:13)
at TLSSocket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at TLSSocket.Readable.push (_stream_readable.js:208:10)
at TLSWrap.onread (net.js:607:20)

2018-04-14T07:45:54.271Z    dbcf48be-3fb7-11e8-bfdc-d96a4e6043b2    0 2825 ==> Connection#handshakeResult(3,Error,66)
sidorares commented 6 years ago

For some reason server does not send AuthSwitchRequest packet in response to initial hello with mysql_native_password data. Protocol allows to start immediately with plugin auth but this is currently not yet supported by client.

You can test this manually by changing mysql_native_password to mysql_clear_password here https://github.com/sidorares/node-mysql2/blob/80c55ef2b60572ef7b0ac7bee2eb45db8de6a516/lib/packets/handshake_response.js#L116 and setting this.authToken to be `password + \0' buffer here - https://github.com/sidorares/node-mysql2/blob/80c55ef2b60572ef7b0ac7bee2eb45db8de6a516/lib/packets/handshake_response.js#L34

Related issues - #560 #550 #438 #332