0
  • Windows 10 Pro
  • MySQL8.0
  • node.js v14.15.5
  • openssl 1.1.1c

I'm trying to connect to a MySQL database using node, I'm able to connect without TLS just fine. I used openssl to create a private key and self signed certificate. When I try to use TLS in my node app, I keep getting the following error:

$ NODE_TLS_REJECT_UNAUTHORIZED=0 node index.js
(node:15480) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
(Use `node --trace-warnings ...` to show where the warning was created)
Error: self signed certificate in certificate chain       
    at TLSSocket.onConnectSecure (_tls_wrap.js:1497:34)   
    at TLSSocket.emit (events.js:315:20)
    at TLSSocket._finishInit (_tls_wrap.js:932:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:706:12) {
  code: 'SELF_SIGNED_CERT_IN_CHAIN'
}
TypeError: Cannot read property 'sql' of undefined
    at C:\Users\gregb\Desktop\PROGRAMMING\VS Code Workspace\xdevapi2\index.js:40:32
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
[]
[]

Index.js

let mysqlx = require('@mysql/xdevapi');
let fs = require('fs'); 
require('dotenv').config();

let rows = [];
let columns = [];

// Works without TLS
// let config = {
//     host: 'localhost',
//     port: 33060,
//     user: 'root',
//     database: 'user',
//     password: process.env.password
// };

const config = {
    host: 'localhost', 
    port: 33060,     
    user: 'root',
    database: 'user',    
    password: process.env.password,
    ssl: true,
    tls: {
      rejectUnauthorized: false,
      key: fs.readFileSync('./privatekey2.pem'), 
      cert: fs.readFileSync('./example.crt'),
      ca: './cacert.pem'
    }
};

(async function () {
    let session;
try {
    session = await mysqlx.getSession(config);
} catch(err) {
    console.log(err);
}  

try {
    let result = await session.sql('SELECT "firstName" AS c1, "lastName" AS c2')       
    .execute(row => rows.push(row), column => columns = columns.concat(column));
    session.close();
} catch(err) {
    console.log(err);
}    
    console.log(rows); // [['foo', 'bar']]
    console.log(columns.map(column => column.getColumnLabel())); // ['c1', 'c2']        
})();

I also tried:

NODE_TLS_REJECT_UNAUTHORIZED='0' node index.js

How I used openssl:

  1. Create a public/private key file pair:
openssl genrsa -out privkey2.pem 4096
  1. Split into public/private:
openssl ssh-keygen -t rsa -b 4096 -f privatekey2.pem
  1. Create a cert
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout privatekey2.pem -out example.crt
LarryN
  • 216
  • 1
  • 2
  • 12

1 Answers1

0

The problem does not seem to be related to the certificate you are using. It should be related to the fact that you provide a path for the certificate authority file (ca). You do this when you want the client to verify that the server certificate was signed using a certificate in the CA chain, which only works if rejectUnauthorized is true, which is automatically set once you provide that valid CA file path, thus, your custom rejectUnauthorized: false is ignored.

Which begs the question, Is the server certificate signed by the CA you are providing? I suspect it is not, in which case, the error is legitimate.

If so, then it is a bug, and you should report it using the public MySQL issue tracker. However, I ran a few tests and I'm convinced there is no issue, but if you are able to produce a server certificate that was, indeed, signed by that particular CA, which allows to reproduce the same exact scenario, maybe we can dig some dirt.

Disclaimer: I'm the lead developer of MySQL X DevAPI Connector for Node.js

ruiquelhas
  • 1,905
  • 1
  • 17
  • 17