Redis client cannot connect to Redis Server due to TLS cert error
younes-io opened this issue · comments
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
I'm confused.. wanna debug it together?
I'll be here for the next 15 minutes
@younes-io did you manage to solve it?
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.