redis / node-redis

Redis Node.js client

Home Page:https://redis.js.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Redis client cannot connect to Redis Server due to TLS cert error

younes-io opened this issue · comments

commented

I have this bit of code:

    console.log(`Creating Redis client`);
    const redisClient = createClient({
        url: process.env.REDIS_URL,
        socket: {
            tls: false, // ==> also tried 'true', but same issue
            rejectUnauthorized: false,
            requestCert: false,
        },
    });
    console.log(`Starting Redis connection`);
    await redisClient.connect();
    console.log(`Redis connection completed`);

process.env.REDIS_URL has a value of this format : rediss://$USERNAME:$PASSWORD@$HOST:$PORT/0

I get this error when I run it:

Creating Redis client
Starting Redis connection
Error: error:0909006C:PEM routines:get_name:no start line
    at node:internal/tls/secure-context:65:13
    at Array.forEach (<anonymous>)
    at setCerts (node:internal/tls/secure-context:63:3)
    at configSecureContext (node:internal/tls/secure-context:152:5)
    at Object.createSecureContext (node:_tls_common:117:3)
    at Object.connect (node:_tls_wrap:1621:48)
    at RedisSocket._RedisSocket_createTlsSocket (/home/project/backend/node_modules/@redis/client/dist/lib/client/socket.js:200:21)
    at /home/project/backend/node_modules/@redis/client/dist/lib/client/socket.js:161:101
    at new Promise (<anonymous>)
    at RedisSocket._RedisSocket_createSocket (/home/project/backend/node_modules/@redis/client/dist/lib/client/socket.js:159:12) {
  library: 'PEM routines',
  function: 'get_name',
  reason: 'no start line',
  code: 'ERR_OSSL_PEM_NO_START_LINE'
}
[nodemon] app crashed - waiting for file changes before starting...

I don't understand why do I have this error even though I'm not using any certificate at all...

Environment:

  • Node.js Version: v16.13.2
  • Redis Server Version: 6
  • Node Redis Version: 4.5.1
  • Platform: Ubuntu 20.04.3

if the URL protocol is "rediss" (with double s) it'll use TLS

commented

@leibale : whether I use redis or rediss, it's the same...

I'm confused.. wanna debug it together?

I'll be here for the next 15 minutes

@younes-io did you manage to solve it?

commented

@leibale Not really, I just switched to the older version of the package :/

I started with the Heroku docs on connecting with TLS in Node. They propose the following approach:

const redis = require("redis");

const client = redis.createClient({
  url: process.env.REDIS_URL,
  tls: {
    rejectUnauthorized: false
  }
});

Which led to the error:
2023-03-27T19:14:27.572166+00:00 app[web.1]: Redis Client Error Error: self-signed certificate in certificate chain
2023-03-27T19:14:27.572185+00:00 app[web.1]: at TLSSocket.onConnectSecure (node:_tls_wrap:1540:34)
2023-03-27T19:14:27.572186+00:00 app[web.1]: at TLSSocket.emit (node:events:513:28)
2023-03-27T19:14:27.572186+00:00 app[web.1]: at TLSSocket._finishInit (node:_tls_wrap:959:8)
2023-03-27T19:14:27.572186+00:00 app[web.1]: at ssl.onhandshakedone (node:_tls_wrap:743:12) {
2023-03-27T19:14:27.572186+00:00 app[web.1]: code: 'SELF_SIGNED_CERT_IN_CHAIN'

It took me too long to consider that Heroku would have a non-working / dated pattern on their help but eventually looked at the node-redis config page
The pattern there for self-signed certs worked, though I dropped the cert: '...' property as follows.

createClient({
  socket: {
    tls: true,
    rejectUnauthorized: false,
  }
});

I didn't open a ticket for Heroku to update their docs because I'm not sure that approach couldn't/shouldn't work in some context other than my own.

If anyone can shed some light on how even the self-signed cert seems to be optional I'd be interested to learn how that's handled on Heroku.

node version: 18.15.0
node-redis: 4.6.5

@builder173 thanks for the heads-up, I'll ask Heroku to update their documentation :)

edit:
Sorry, but I don't understand your question about the self-signed cert...

Thanks for reaching out to Heroku.

I'll try to add some structure to the self-signed cert question. I'm basically trying to figure out why my connection worked without specifying the cert: '...' property that appears in the node-redis examples. Looking through to the tls.connect() docs, perhaps this is only needed when server verifies the client certificate in 2-way ssl? (and apparently Heroku redis doesn't?)

//From tls.connect() docs
const options = {
  // Necessary only if the server requires client certificate authentication.
  key: fs.readFileSync('client-key.pem'),
  cert: fs.readFileSync('client-cert.pem'),

@builder173 because you have rejectUnauthorized set to false, which means the certificate is not verified... You can read more about that here.

So then can/should the cert: '...' property be removed from the last example in the node-redis config page? If I understand what you're saying, you wouldn't specify that property together with rejectUnauthorized: false.

Please share if there is any solution for this issue.
I am getting similar issue after upgrading my redis module in express.js app and heroku redis addon version to latest ones.
Here is my issue details - #2540