You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-07 13:22:56 +03:00
Improve tls tests
Removed redundant tests. Skip the tests on windows instead of not even showing them. Add a faulty cert to check proper cert validation. Reject unauthorized certs
This commit is contained in:
19
test/conf/faulty.cert
Normal file
19
test/conf/faulty.cert
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDATCCAemgAwIBAgIJALkMmVkQOERnMA0GCSqGSIb3DQEBBQUAMBcxFTATBgNV
|
||||||
|
BAMMDHJlZGlzLmpzLm9yZzAeFw0xNTEwMTkxMjIzMjRaFw0yNTEwMTYxMjIzMjRa
|
||||||
|
MBcxFTATBgNVBAMMDHJlZGlzLmpzLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
|
ADCCAQoCggEBAJ/DmMTJHf7kyspxI1A/JmOc+KI9vxEcN5qn7IiZuGN7ghE43Q3q
|
||||||
|
XB2GUkMAuW1POkmM5yi3SuT1UXDR/4Gk7KlbHKMs37AV6PgJXX6oX0zu12LTAT7V
|
||||||
|
5byNrYtehSo42l1188dGEMCGaaf0cDntc7A3aW0ZtzrJt+2pu31Uatl2SEJCMra6
|
||||||
|
+v6O0c9aHMF1cArKeawGqR+jHw6vXFZQbUd06nW5nQlUA6wVt1JjlLPwBwYsWLsi
|
||||||
|
YQxMC8NqpgAIg5tULSCpKwx5isL/CeotVVGDNZ/G8R1nTrxuygPlc3Qskj57hmV4
|
||||||
|
tZK4JJxQFi7/9ehvjAvHohKrEPeqV5XL87cCAwEAAaNQME4wHQYDVR0OBBYEFCn/
|
||||||
|
5hB+XY4pVOnaqvrmZMxrLFjLMB8GA1UdIwQYMBaAFCn/5hB+XY4pVOnaqvrmZMxr
|
||||||
|
LFjLMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAEduPyTHpXkCVZRQ
|
||||||
|
v6p+Ug4iVeXpxGCVr34y7EDUMgmuDdqsz1SrmqeDd0VmjZT8htbWw7QBKDPEBsbi
|
||||||
|
wl606aAn01iM+oUrwbtXxid1xfZj/j6pIhQVkGu7e/8A7Pr4QOP4OMdHB7EmqkAo
|
||||||
|
d/OLHa9LdKv2UtJHD6U7oVQbdBHrRV62125GMmotpQuSkEfZM6edKNzHPlqV/zJc
|
||||||
|
2kGCw3lZC21mTrsSMIC/FQiobPnig4kAvfh0of2rK/XAntlwT8ie1v1aK+jERsfm
|
||||||
|
uzMihl6XXBdzheq6KdIlf+5STHBIIRcvBoRKr5Va7EhnO03tTzeJowtqDv47yPC6
|
||||||
|
w4kLcP8=
|
||||||
|
-----END CERTIFICATE-----
|
251
test/tls.spec.js
251
test/tls.spec.js
@@ -6,25 +6,33 @@ var fs = require('fs');
|
|||||||
var helper = require('./helper');
|
var helper = require('./helper');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var redis = config.redis;
|
var redis = config.redis;
|
||||||
|
var utils = require('../lib/utils');
|
||||||
|
|
||||||
var tls_options = {
|
var tls_options = {
|
||||||
servername: "redis.js.org",
|
servername: "redis.js.org",
|
||||||
rejectUnauthorized: false,
|
rejectUnauthorized: true,
|
||||||
ca: [ String(fs.readFileSync(path.resolve(__dirname, "./conf/redis.js.org.cert"))) ]
|
ca: [ String(fs.readFileSync(path.resolve(__dirname, "./conf/redis.js.org.cert"))) ]
|
||||||
};
|
};
|
||||||
|
|
||||||
var tls_port = 6380;
|
var tls_port = 6380;
|
||||||
|
// Use skip instead of returning to indicate what tests really got skipped
|
||||||
if (process.platform === 'win32') {
|
var skip = false;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until stunnel4 is in the travis whitelist
|
// Wait until stunnel4 is in the travis whitelist
|
||||||
// Check: https://github.com/travis-ci/apt-package-whitelist/issues/403
|
// Check: https://github.com/travis-ci/apt-package-whitelist/issues/403
|
||||||
// If this is merged, remove the travis env checks
|
// If this is merged, remove the travis env checks
|
||||||
describe("TLS connection tests", function () {
|
describe("TLS connection tests", function () {
|
||||||
|
|
||||||
before(function (done) {
|
before(function (done) {
|
||||||
if (process.env.TRAVIS === 'true') {
|
// Print the warning when the tests run instead of while starting mocha
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
skip = true;
|
||||||
|
console.warn('\nStunnel tests do not work on windows atm. If you think you can fix that, it would be warmly welcome.\n');
|
||||||
|
} else if (process.env.TRAVIS === 'true') {
|
||||||
|
skip = true;
|
||||||
|
console.warn('\nTravis does not support stunnel right now. Skipping tests.\nCheck: https://github.com/travis-ci/apt-package-whitelist/issues/403\n');
|
||||||
|
}
|
||||||
|
if (skip) {
|
||||||
done();
|
done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -34,188 +42,87 @@ describe("TLS connection tests", function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
after(function (done) {
|
after(function (done) {
|
||||||
if (process.env.TRAVIS === 'true') {
|
if (skip) {
|
||||||
done();
|
done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
helper.stopStunnel(done);
|
helper.stopStunnel(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
helper.allTests(function(parser, ip, args) {
|
var client;
|
||||||
|
|
||||||
describe("using " + parser + " and " + ip, function () {
|
afterEach(function () {
|
||||||
|
client.end(true);
|
||||||
|
});
|
||||||
|
|
||||||
var client;
|
describe("on lost connection", function () {
|
||||||
|
it("emit an error after max retry timeout and do not try to reconnect afterwards", function (done) {
|
||||||
|
if (skip) this.skip();
|
||||||
|
var connect_timeout = 500; // in ms
|
||||||
|
client = redis.createClient({
|
||||||
|
connect_timeout: connect_timeout,
|
||||||
|
port: tls_port,
|
||||||
|
tls: tls_options
|
||||||
|
});
|
||||||
|
var time = 0;
|
||||||
|
|
||||||
afterEach(function () {
|
client.once('ready', function() {
|
||||||
client.end(true);
|
helper.killConnection(client);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("on lost connection", function () {
|
client.on("reconnecting", function (params) {
|
||||||
it("emit an error after max retry attempts and do not try to reconnect afterwards", function (done) {
|
time += params.delay;
|
||||||
if (process.env.TRAVIS === 'true') this.skip();
|
|
||||||
var max_attempts = 4;
|
|
||||||
var options = {
|
|
||||||
parser: parser,
|
|
||||||
max_attempts: max_attempts,
|
|
||||||
port: tls_port,
|
|
||||||
tls: tls_options
|
|
||||||
};
|
|
||||||
client = redis.createClient(options);
|
|
||||||
var calls = 0;
|
|
||||||
|
|
||||||
client.once('ready', function() {
|
|
||||||
helper.killConnection(client);
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on("reconnecting", function (params) {
|
|
||||||
calls++;
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('error', function(err) {
|
|
||||||
if (/Redis connection in broken state: maximum connection attempts.*?exceeded./.test(err.message)) {
|
|
||||||
setTimeout(function () {
|
|
||||||
assert.strictEqual(calls, max_attempts - 1);
|
|
||||||
done();
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("emit an error after max retry timeout and do not try to reconnect afterwards", function (done) {
|
|
||||||
if (process.env.TRAVIS === 'true') this.skip();
|
|
||||||
var connect_timeout = 500; // in ms
|
|
||||||
client = redis.createClient({
|
|
||||||
parser: parser,
|
|
||||||
connect_timeout: connect_timeout,
|
|
||||||
port: tls_port,
|
|
||||||
tls: tls_options
|
|
||||||
});
|
|
||||||
var time = 0;
|
|
||||||
|
|
||||||
client.once('ready', function() {
|
|
||||||
helper.killConnection(client);
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on("reconnecting", function (params) {
|
|
||||||
time += params.delay;
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('error', function(err) {
|
|
||||||
if (/Redis connection in broken state: connection timeout.*?exceeded./.test(err.message)) {
|
|
||||||
setTimeout(function () {
|
|
||||||
assert(time === connect_timeout);
|
|
||||||
done();
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("end connection while retry is still ongoing", function (done) {
|
|
||||||
if (process.env.TRAVIS === 'true') this.skip();
|
|
||||||
var connect_timeout = 1000; // in ms
|
|
||||||
client = redis.createClient({
|
|
||||||
parser: parser,
|
|
||||||
connect_timeout: connect_timeout,
|
|
||||||
port: tls_port,
|
|
||||||
tls: tls_options
|
|
||||||
});
|
|
||||||
|
|
||||||
client.once('ready', function() {
|
|
||||||
helper.killConnection(client);
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on("reconnecting", function (params) {
|
|
||||||
client.end(true);
|
|
||||||
setTimeout(done, 100);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("can not connect with wrong host / port in the options object", function (done) {
|
|
||||||
if (process.env.TRAVIS === 'true') this.skip();
|
|
||||||
var options = {
|
|
||||||
host: 'somewhere',
|
|
||||||
max_attempts: 1,
|
|
||||||
port: tls_port,
|
|
||||||
tls: tls_options
|
|
||||||
};
|
|
||||||
client = redis.createClient(options);
|
|
||||||
var end = helper.callFuncAfter(done, 2);
|
|
||||||
|
|
||||||
client.on('error', function (err) {
|
|
||||||
assert(/CONNECTION_BROKEN|ENOTFOUND|EAI_AGAIN/.test(err.code));
|
|
||||||
end();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when not connected", function () {
|
client.on('error', function(err) {
|
||||||
|
if (/Redis connection in broken state: connection timeout.*?exceeded./.test(err.message)) {
|
||||||
it("connect with host and port provided in the options object", function (done) {
|
setTimeout(function () {
|
||||||
if (process.env.TRAVIS === 'true') this.skip();
|
assert(time === connect_timeout);
|
||||||
client = redis.createClient({
|
|
||||||
host: 'localhost',
|
|
||||||
parser: parser,
|
|
||||||
connect_timeout: 1000,
|
|
||||||
port: tls_port,
|
|
||||||
tls: tls_options
|
|
||||||
});
|
|
||||||
|
|
||||||
client.once('ready', function() {
|
|
||||||
done();
|
done();
|
||||||
});
|
}, 100);
|
||||||
});
|
|
||||||
|
|
||||||
it("connects correctly with args", function (done) {
|
|
||||||
if (process.env.TRAVIS === 'true') this.skip();
|
|
||||||
var args_host = args[1];
|
|
||||||
var args_options = args[2] || {};
|
|
||||||
args_options.tls = tls_options;
|
|
||||||
client = redis.createClient(tls_port, args_host, args_options);
|
|
||||||
client.on("error", done);
|
|
||||||
|
|
||||||
client.once("ready", function () {
|
|
||||||
client.removeListener("error", done);
|
|
||||||
client.get("recon 1", function (err, res) {
|
|
||||||
done(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ip === 'IPv4') {
|
|
||||||
it('allows connecting with the redis url and no auth and options as second parameter', function (done) {
|
|
||||||
if (process.env.TRAVIS === 'true') this.skip();
|
|
||||||
var options = {
|
|
||||||
detect_buffers: false,
|
|
||||||
magic: Math.random(),
|
|
||||||
port: tls_port,
|
|
||||||
tls: tls_options
|
|
||||||
};
|
|
||||||
client = redis.createClient('redis://' + config.HOST[ip] + ':' + tls_port, options);
|
|
||||||
// verify connection is using TCP, not UNIX socket
|
|
||||||
assert.strictEqual(client.connection_options.host, config.HOST[ip]);
|
|
||||||
assert.strictEqual(client.connection_options.port, tls_port);
|
|
||||||
assert(typeof client.stream.getCipher === 'function');
|
|
||||||
// verify passed options are in use
|
|
||||||
assert.strictEqual(client.options.magic, options.magic);
|
|
||||||
client.on("ready", function () {
|
|
||||||
return done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('allows connecting with the redis url and no auth and options as third parameter', function (done) {
|
|
||||||
if (process.env.TRAVIS === 'true') this.skip();
|
|
||||||
client = redis.createClient('redis://' + config.HOST[ip] + ':' + tls_port, null, {
|
|
||||||
detect_buffers: false,
|
|
||||||
tls: tls_options
|
|
||||||
});
|
|
||||||
client.on("ready", function () {
|
|
||||||
return done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("when not connected", function () {
|
||||||
|
|
||||||
|
it("connect with host and port provided in the options object", function (done) {
|
||||||
|
if (skip) this.skip();
|
||||||
|
client = redis.createClient({
|
||||||
|
host: 'localhost',
|
||||||
|
connect_timeout: 1000,
|
||||||
|
port: tls_port,
|
||||||
|
tls: tls_options
|
||||||
|
});
|
||||||
|
|
||||||
|
// verify connection is using TCP, not UNIX socket
|
||||||
|
assert.strictEqual(client.connection_options.host, 'localhost');
|
||||||
|
assert.strictEqual(client.connection_options.port, tls_port);
|
||||||
|
assert(client.stream.encrypted);
|
||||||
|
|
||||||
|
client.set('foo', 'bar');
|
||||||
|
client.get('foo', helper.isString('bar', done));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails to connect because the cert is not correct', function (done) {
|
||||||
|
if (skip) this.skip();
|
||||||
|
var faulty_cert = utils.clone(tls_options);
|
||||||
|
faulty_cert.ca = [ String(fs.readFileSync(path.resolve(__dirname, "./conf/faulty.cert"))) ];
|
||||||
|
client = redis.createClient({
|
||||||
|
host: 'localhost',
|
||||||
|
connect_timeout: 1000,
|
||||||
|
port: tls_port,
|
||||||
|
tls: faulty_cert
|
||||||
|
});
|
||||||
|
client.on('error', function (err) {
|
||||||
|
assert.strictEqual(err.code, 'DEPTH_ZERO_SELF_SIGNED_CERT');
|
||||||
|
client.end(true);
|
||||||
|
});
|
||||||
|
client.set('foo', 'bar', function (err, res) {
|
||||||
|
done(res);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user