Skip to content

Commit cca588a

Browse files
committed
MLE-16819 : Support TLSv1.3 via Node Client
1 parent 5fe6126 commit cca588a

File tree

3 files changed

+199
-1
lines changed

3 files changed

+199
-1
lines changed

etc/test-config.js

+9
Original file line numberDiff line numberDiff line change
@@ -148,5 +148,14 @@ module.exports = {
148148
host: testHost,
149149
port: restPort,
150150
authType: 'oauth'
151+
},
152+
restConnectionForTls: {
153+
host: testHost,
154+
port: restPort,
155+
user: restWriterUser,
156+
password: restWriterPassword,
157+
authType: restAuthType,
158+
ssl: true,
159+
rejectUnauthorized: false
151160
}
152161
};

lib/marklogic.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ function initClient(client, inputParams) {
732732
'enableGzippedResponses', 'oauthToken'];
733733
if(isSSL) {
734734
keys.push('ca', 'cert', 'ciphers', 'clientCertEngine', 'crl', 'dhparam', 'ecdhCurve', 'honorCipherOrder', 'key', 'passphrase',
735-
'pfx', 'rejectUnauthorized', 'secureOptions', 'secureProtocol', 'servername', 'sessionIdContext', 'highWaterMark');
735+
'pfx', 'rejectUnauthorized', 'secureOptions', 'secureProtocol', 'servername', 'sessionIdContext', 'highWaterMark', 'agent');
736736
}
737737
for (var i=0; i < keys.length; i++) {
738738
var key = keys[i];

test-basic/ssl-min-allow-tls-test.js

+189
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/*
2+
* Copyright (c) 2025 MarkLogic Corporation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
let testconfig = require('../etc/test-config.js');
18+
let should = require('should');
19+
let marklogic = require('../');
20+
const { exec } = require('child_process');
21+
const testlib = require("../etc/test-lib");
22+
let db = marklogic.createDatabaseClient(testconfig.restConnectionForTls);
23+
let serverConfiguration = {};
24+
describe('ssl-min-allow-tls-test', function() {
25+
this.timeout(10000);
26+
before(function (done) {
27+
testlib.findServerConfiguration(serverConfiguration);
28+
setTimeout(() => {
29+
done();
30+
}, 2000);
31+
});
32+
describe('document write and read using min tls', function () {
33+
34+
before(function (done) {
35+
if (serverConfiguration.serverVersion < 12) {
36+
this.skip();
37+
}
38+
createAndSetupTemplate("test-template", done);
39+
});
40+
41+
after(function (done) {
42+
sslReset().then(() => {
43+
testconfig.restConnectionForTls.ssl = false;
44+
testconfig.restConnectionForTls.agent = null;
45+
db = marklogic.createDatabaseClient(testconfig.restConnectionForTls);
46+
db.documents.remove('/test/write_tlsV1.3.json', '/test/write_tlsV1.2.json')
47+
.result(() => done())
48+
.catch(error => done(error));
49+
});
50+
});
51+
52+
it('should write document with minimum TLS versions 1.3', function (done) {
53+
updateTlsVersion('TLSv1.3').then((result) => {
54+
db.documents.write({
55+
uri: '/test/write_tlsV1.3.json',
56+
contentType: 'application/json',
57+
content: '{"key1":"With TLS 1.3"}'
58+
}).result(function (response) {
59+
db.documents.read('/test/write_tlsV1.3.json')
60+
.result(function (documents) {
61+
documents[0].content.should.have.property('key1');
62+
documents[0].content.key1.should.equal('With TLS 1.3');
63+
64+
}).then(() => done())
65+
.catch(error => done(error));
66+
})
67+
})
68+
});
69+
70+
it('should write document with minimum TLS versions 1.2', function (done) {
71+
updateTlsVersion('TLSv1.2').then((result) => {
72+
db.documents.write({
73+
uri: '/test/write_tlsV1.2.json',
74+
contentType: 'application/json',
75+
content: '{"key1":"With TLS 1.2"}'
76+
}).result(function (response) {
77+
db.documents.read('/test/write_tlsV1.2.json')
78+
.result(function (documents) {
79+
documents[0].content.should.have.property('key1');
80+
documents[0].content.key1.should.equal('With TLS 1.2');
81+
82+
}).then(() => done())
83+
.catch(error => done(error));
84+
})
85+
})
86+
});
87+
88+
it('should throw error when user sets 1.2 and server needs 1.3', function (done) {
89+
const https = require('https');
90+
const tlsAgent = new https.Agent({
91+
keepAlive: true,
92+
minVersion: 'TLSv1.2',
93+
maxVersion: 'TLSv1.2'
94+
});
95+
testconfig.restConnectionForTls.agent = tlsAgent;
96+
db = marklogic.createDatabaseClient(testconfig.restConnectionForTls);
97+
updateTlsVersion('TLSv1.3').then(() => {
98+
db.documents.write({
99+
uri: '/test/write_tlsV1.2.json',
100+
contentType: 'application/json',
101+
content: '{"key1":"With TLS 1.2"}'
102+
}).result(() => done()).catch(error => {
103+
// TLS handshake error.
104+
error.message.should.containEql("error:0A00042E:SSL routines")
105+
done();
106+
})
107+
})
108+
});
109+
})
110+
111+
function updateTlsVersion(tlsVersion) {
112+
return new Promise((resolve, reject) => {
113+
const curlCommand = `
114+
curl --anyauth --user admin:admin -X PUT -H "Content-Type: application/json" \
115+
-d '{"ssl-min-allow-tls": "${tlsVersion}"}' \
116+
'http://localhost:8002/manage/v2/servers/unittest-nodeapi/properties?group-id=Default'
117+
`;
118+
exec(curlCommand, (error, stdout, stderr) => {
119+
if (error) {
120+
throw new Error(`Error executing curl: ${stderr}`);
121+
}
122+
resolve();
123+
});
124+
});
125+
}
126+
127+
function createAndSetupTemplate(templateName, done) {
128+
return new Promise((resolve, reject) => {
129+
const curlCommand = `
130+
curl -X POST --anyauth -u admin:admin --header "Content-Type:application/json" \\
131+
-d '{
132+
"template-name": "${templateName}",
133+
"template-description": "My Template",
134+
"key-type": "rsa",
135+
"key-options": {
136+
"key-length": "2048"
137+
},
138+
"req": {
139+
"version": "0",
140+
"subject": {
141+
"organizationName": "MarkLogic"
142+
}
143+
}
144+
}' http://localhost:8002/manage/v2/certificate-templates
145+
`;
146+
exec(curlCommand, (error, stdout, stderr) => {
147+
if (error) {
148+
throw new Error(`Error executing curl: ${stderr}`);
149+
}
150+
return new Promise((resolve, reject) => {
151+
const command = `curl --anyauth --user admin:admin -X PUT -H "Content-Type: application/json" \\
152+
-d '{
153+
"ssl-certificate-template": "${templateName}",
154+
"ssl-require-client-certificate":false
155+
}' \\
156+
'http://localhost:8002/manage/v2/servers/unittest-nodeapi/properties?group-id=Default'`;
157+
158+
exec(command, (error, stdout, stderr) => {
159+
if (error) {
160+
throw new Error(`Error executing curl: ${stderr}`);
161+
}
162+
done();
163+
})
164+
165+
});
166+
});
167+
})
168+
}
169+
170+
function sslReset() {
171+
return new Promise((resolve, reject) => {
172+
const command = `curl --anyauth --user admin:admin -X PUT -H "Content-Type: application/json" \\
173+
-d '{
174+
"ssl-certificate-template": null,
175+
"ssl-require-client-certificate":true,
176+
"ssl-min-allow-tls": "TLSv1.2"
177+
}' \\
178+
'http://localhost:8002/manage/v2/servers/unittest-nodeapi/properties?group-id=Default'`;
179+
180+
exec(command, (error, stdout, stderr) => {
181+
if (error) {
182+
throw new Error(`Error executing curl: ${stderr}`);
183+
}
184+
resolve();
185+
})
186+
187+
});
188+
}
189+
});

0 commit comments

Comments
 (0)