Skip to content

Deprecate TRUST_SIGNED_CERTIFICATES #124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 5, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/v1/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,15 +196,18 @@ let USER_AGENT = "neo4j-javascript/" + VERSION;
* // This means that by default, connections "just work" while still giving you
* // good encrypted protection.
* //
* // TRUST_SIGNED_CERTIFICATES is the classic approach to trust verification -
* // TRUST_CUSTOM_CA_SIGNED_CERTIFICATES is the classic approach to trust verification -
* // whenever we establish an encrypted connection, we ensure the host is using
* // an encryption certificate that is in, or is signed by, a certificate listed
* // as trusted. In the web bundle, this list of trusted certificates is maintained
* // by the web browser. In NodeJS, you configure the list with the next config option.
* trust: "TRUST_ON_FIRST_USE" | "TRUST_SIGNED_CERTIFICATES",
* //
* // TRUST_SYSTEM_CA_SIGNED_CERTIFICATES meand that you trust whatever certificates
* // are in the default certificate chain of th
* trust: "TRUST_ON_FIRST_USE" | "TRUST_SIGNED_CERTIFICATES" | TRUST_CUSTOM_CA_SIGNED_CERTIFICATES | TRUST_SYSTEM_CA_SIGNED_CERTIFICATES,
*
* // List of one or more paths to trusted encryption certificates. This only
* // works in the NodeJS bundle, and only matters if you use "TRUST_SIGNED_CERTIFICATES".
* // works in the NodeJS bundle, and only matters if you use "TRUST_CUSTOM_CA_SIGNED_CERTIFICATES".
* // The certificate files should be in regular X.509 PEM format.
* // For instance, ['./trusted.pem']
* trustedCertificates: [],
Expand Down
39 changes: 35 additions & 4 deletions src/v1/internal/ch-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,17 @@ function storeFingerprint( serverId, knownHostsPath, fingerprint, cb ) {
}

const TrustStrategy = {
TRUST_SIGNED_CERTIFICATES : function( opts, onSuccess, onFailure ) {
/**
* @deprecated Since version 1.0. Will be deleted in a future version. TRUST_CUSTOM_CA_SIGNED_CERTIFICATES.
*/
TRUST_SIGNED_CERTIFICATES: function( opts, onSuccess, onFailure ) {
console.log("`TRUST_SIGNED_CERTIFICATES` has been deprecated as option and will be removed in a future version of " +
"the driver. Pleas use `TRUST_CUSTOM_CA_SIGNED_CERTIFICATES` instead.");
return TrustStrategy.TRUST_CUSTOM_CA_SIGNED_CERTIFICATES(opts, onSuccess, onFailure);
},
TRUST_CUSTOM_CA_SIGNED_CERTIFICATES : function( opts, onSuccess, onFailure ) {
if( !opts.trustedCertificates || opts.trustedCertificates.length == 0 ) {
onFailure(newError("You are using TRUST_SIGNED_CERTIFICATES as the method " +
onFailure(newError("You are using TRUST_CUSTOM_CA_SIGNED_CERTIFICATES as the method " +
"to verify trust for encrypted connections, but have not configured any " +
"trustedCertificates. You must specify the path to at least one trusted " +
"X.509 certificate for this to work. Two other alternatives is to use " +
Expand Down Expand Up @@ -137,6 +145,29 @@ const TrustStrategy = {
socket.on('error', onFailure);
return socket;
},
TRUST_SYSTEM_CA_SIGNED_CERTIFICATES : function( opts, onSuccess, onFailure ) {

let tlsOpts = {
// Because we manually check for this in the connect callback, to give
// a more helpful error to the user
rejectUnauthorized: false
};
let socket = tls.connect(opts.port, opts.host, tlsOpts, function () {
if (!socket.authorized) {
onFailure(newError("Server certificate is not trusted. If you trust the database you are connecting to, use " +
"TRUST_CUSTOM_CA_SIGNED_CERTIFICATES and add" +
" the signing certificate, or the server certificate, to the list of certificates trusted by this driver" +
" using `neo4j.v1.driver(.., { trustedCertificates:['path/to/certificate.crt']}). This " +
" is a security measure to protect against man-in-the-middle attacks. If you are just trying " +
" Neo4j out and are not concerned about encryption, simply disable it using `encrypted=false` in the driver" +
" options."));
} else {
onSuccess();
}
});
socket.on('error', onFailure);
return socket;
},
TRUST_ON_FIRST_USE : function( opts, onSuccess, onFailure ) {
let tlsOpts = {
// Because we manually verify the certificate against known_hosts
Expand All @@ -153,7 +184,7 @@ const TrustStrategy = {
// do TOFU, and the safe approach is to fail.
onFailure(newError("You are using a version of NodeJS that does not " +
"support trust-on-first use encryption. You can either upgrade NodeJS to " +
"a newer version, use `trust:TRUST_SIGNED_CERTIFICATES` in your driver " +
"a newer version, use `trust:TRUST_CUSTOM_CA_SIGNED_CERTIFICATES` in your driver " +
"config instead, or disable encryption using `encrypted:false`."));
return;
}
Expand Down Expand Up @@ -201,7 +232,7 @@ function connect( opts, onSuccess, onFailure=(()=>null) ) {
return TrustStrategy[opts.trust](opts, onSuccess, onFailure);
} else {
onFailure(newError("Unknown trust strategy: " + opts.trust + ". Please use either " +
"trust:'TRUST_SIGNED_CERTIFICATES' or trust:'TRUST_ON_FIRST_USE' in your driver " +
"trust:'TRUST_CUSTOM_CA_SIGNED_CERTIFICATES' or trust:'TRUST_ON_FIRST_USE' in your driver " +
"configuration. Alternatively, you can disable encryption by setting " +
"`encrypted:false`. There is no mechanism to use encryption without trust verification, " +
"because this incurs the overhead of encryption without improving security. If " +
Expand Down
6 changes: 3 additions & 3 deletions src/v1/internal/ch-websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ class WebSocketChannel {

let scheme = "ws";
if( opts.encrypted ) {
if( (!opts.trust) || opts.trust === "TRUST_SIGNED_CERTIFICATES" ) {
if( (!opts.trust) || opts.trust === "TRUST_SIGNED_CERTIFICATES" || opts.trust === "TRUST_CUSTOM_CA_SIGNED_CERTIFICATES" ) {
scheme = "wss";
} else {
this._error = newError("The browser version of this driver only supports one trust " +
"strategy, 'TRUST_SIGNED_CERTIFICATES'. "+opts.trust+" is not supported. Please " +
"either use TRUST_SIGNED_CERTIFICATES or disable encryption by setting " +
"strategy, 'TRUST_CUSTOM_CA_SIGNED_CERTIFICATES'. "+opts.trust+" is not supported. Please " +
"either use TRUST_CUSTOM_CA_SIGNED_CERTIFICATES or disable encryption by setting " +
"`encrypted:false` in the driver configuration.");
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/v1/internal/connector.js
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ function connect( url, config = {}) {
// Default to using encryption if trust-on-first-use is available
encrypted : (config.encrypted == null) ? hasFeature("trust_on_first_use") : config.encrypted,
// Default to using trust-on-first-use if it is available
trust : config.trust || (hasFeature("trust_on_first_use") ? "TRUST_ON_FIRST_USE" : "TRUST_SIGNED_CERTIFICATES"),
trust : config.trust || (hasFeature("trust_on_first_use") ? "TRUST_ON_FIRST_USE" : "TRUST_CUSTOM_CA_SIGNED_CERTIFICATES"),
trustedCertificates : config.trustedCertificates || [],
knownHosts : config.knownHosts
}));
Expand Down
75 changes: 75 additions & 0 deletions test/internal/tls.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,81 @@ describe('trust-signed-certificates', function() {
});
});

describe('trust-custom-ca-signed-certificates', function() {

var driver;

it('should reject unknown certificates', function(done) {
// Assuming we only run this test on NodeJS
if( !NodeChannel.available ) {
done();
return;
}

// Given
driver = neo4j.driver("bolt://localhost", neo4j.auth.basic("neo4j", "neo4j"), {
encrypted: true,
trust: "TRUST_CUSTOM_CA_SIGNED_CERTIFICATES",
trustedCertificates: ["test/resources/random.certificate"]
});

// When
driver.session().run( "RETURN 1").catch( function(err) {
expect( err.message ).toContain( "Server certificate is not trusted" );
done();
});
});

it('should accept known certificates', function(done) {
// Assuming we only run this test on NodeJS with TOFU support
if( !NodeChannel.available ) {
done();
return;
}

// Given
driver = neo4j.driver("bolt://localhost", neo4j.auth.basic("neo4j", "neo4j"), {
encrypted: true,
trust: "TRUST_CUSTOM_CA_SIGNED_CERTIFICATES",
trustedCertificates: ["build/neo4j/certificates/neo4j.cert"]
});

// When
driver.session().run( "RETURN 1").then( done );
});

afterEach(function(){
if( driver ) {
driver.close();
}
});
});

describe('trust-system-ca-signed-certificates', function() {

var driver;

fit('should reject unknown certificates', function(done) {
// Assuming we only run this test on NodeJS
if( !NodeChannel.available ) {
done();
return;
}

// Given
driver = neo4j.driver("bolt://localhost", neo4j.auth.basic("neo4j", "neo4j"), {
encrypted: true,
trust: "TRUST_SYSTEM_CA_SIGNED_CERTIFICATES"
});

// When
driver.session().run( "RETURN 1").catch( function(err) {
expect( err.message ).toContain( "Server certificate is not trusted" );
done();
});
});
});

describe('trust-on-first-use', function() {

var driver;
Expand Down
4 changes: 2 additions & 2 deletions test/v1/examples.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ describe('examples', function() {
var driver = neo4j.driver("bolt://localhost", neo4j.auth.basic("neo4j", "neo4j"), {
// Note that trust-on-first-use is not available in the browser bundle,
// in NodeJS, trust-on-first-use is the default trust mode. In the browser
// it is TRUST_SIGNED_CERTIFICATES.
// it is TRUST_CUSTOM_CA_SIGNED_CERTIFICATES.
trust: "TRUST_ON_FIRST_USE",
encrypted:true
});
Expand All @@ -369,7 +369,7 @@ describe('examples', function() {
var neo4j = neo4jv1;
// tag::tls-signed[]
var driver = neo4j.driver("bolt://localhost", neo4j.auth.basic("neo4j", "neo4j"), {
trust: "TRUST_SIGNED_CERTIFICATES",
trust: "TRUST_CUSTOM_CA_SIGNED_CERTIFICATES",
// Configuring which certificates to trust here is only available
// in NodeJS. In the browser bundle the browsers list of trusted
// certificates is used, due to technical limitations in some browsers.
Expand Down
4 changes: 2 additions & 2 deletions test/v1/tck/steps/tlssteps.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ module.exports = function () {
this.Given(/^a driver configured to use a trusted certificate$/, function (callback) {
this.config = {
encrypted: true,
trust: "TRUST_SIGNED_CERTIFICATES",
trust: "TRUST_CUSTOM_CA_SIGNED_CERTIFICATES",
knownHosts: this.knownHosts1,
trustedCertificates: ['./test/resources/root.cert']
};
Expand All @@ -133,7 +133,7 @@ module.exports = function () {
//common name is not set to localhost
this.config = {
encrypted: true,
trust: "TRUST_SIGNED_CERTIFICATES",
trust: "TRUST_CUSTOM_CA_SIGNED_CERTIFICATES",
knownHosts: this.knownHosts1,
trustedCertificates: [util.neo4jCert]
};
Expand Down