Skip to content

Commit b2c9703

Browse files
committed
MLE-16819 : Support TLSv1.3 via Node Client
1 parent 3352fb1 commit b2c9703

File tree

3 files changed

+180
-1
lines changed

3 files changed

+180
-1
lines changed

etc/test-config.js

+10
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
let testHost = 'localhost';
1717

1818
let restPort = '8015';
19+
let restSslPort = '8016';
1920
let restAuthType = 'DIGEST';
2021

2122
let managePort = '8002';
@@ -148,5 +149,14 @@ module.exports = {
148149
host: testHost,
149150
port: restPort,
150151
authType: 'oauth'
152+
},
153+
restConnectionForTls: {
154+
host: testHost,
155+
port: restSslPort,
156+
user: restWriterUser,
157+
password: restWriterPassword,
158+
authType: restAuthType,
159+
ssl: true,
160+
rejectUnauthorized: false
151161
}
152162
};

lib/marklogic.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,7 @@ function initClient(client, inputParams) {
791791
client.request = https.request;
792792
if (noAgent) {
793793
mlutil.copyProperties(inputParams, agentOptions, [
794-
'keepAliveMsecs', 'maxCachedSessions', 'maxFreeSockets', 'maxSockets', 'maxTotalSockets', 'scheduling', 'timeout'
794+
'keepAliveMsecs', 'maxCachedSessions', 'maxFreeSockets', 'maxSockets', 'maxTotalSockets', 'scheduling', 'timeout', 'minVersion', 'maxVersion'
795795
]);
796796
connectionParams.agent = new https.Agent(agentOptions);
797797
} else {

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

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
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+
let host = testconfig.testHost;
25+
26+
describe('document write and read using min tls', function () {
27+
this.timeout(10000);
28+
before(function (done) {
29+
testlib.findServerConfiguration(serverConfiguration);
30+
setTimeout(() => {
31+
if (serverConfiguration.serverVersion < 12) {
32+
this.skip();
33+
}
34+
done();
35+
}, 3000);
36+
});
37+
38+
it('should write document with minimum TLS versions 1.3', function (done) {
39+
updateTlsVersion('TLSv1.3').then((result) => {
40+
db.documents.write({
41+
uri: '/test/write_tlsV1.3.json',
42+
contentType: 'application/json',
43+
content: '{"key1":"With TLS 1.3"}'
44+
}).result(function (response) {
45+
db.documents.read('/test/write_tlsV1.3.json')
46+
.result(function (documents) {
47+
documents[0].content.should.have.property('key1');
48+
documents[0].content.key1.should.equal('With TLS 1.3');
49+
50+
}).then(() => done())
51+
.catch(error => done(error));
52+
}).catch(error=> done(error));
53+
}).catch(error=> done(error));
54+
});
55+
56+
it('should write document with minimum TLS versions 1.2', function (done) {
57+
updateTlsVersion('TLSv1.2').then((result) => {
58+
db.documents.write({
59+
uri: '/test/write_tlsV1.2.json',
60+
contentType: 'application/json',
61+
content: '{"key1":"With TLS 1.2"}'
62+
}).result(function (response) {
63+
db.documents.read('/test/write_tlsV1.2.json')
64+
.result(function (documents) {
65+
documents[0].content.should.have.property('key1');
66+
documents[0].content.key1.should.equal('With TLS 1.2');
67+
68+
}).then(() => done())
69+
.catch(error => done(error));
70+
}).catch(error=> done(error));
71+
}).catch(error=> done(error));
72+
});
73+
74+
it('should throw error when user strictly sets 1.2 and server needs min TLS version as 1.3', function (done) {
75+
testconfig.restConnectionForTls.minVersion = 'TLSv1.2';
76+
testconfig.restConnectionForTls.maxVersion = 'TLSv1.2';
77+
db = marklogic.createDatabaseClient(testconfig.restConnectionForTls);
78+
updateTlsVersion('TLSv1.3').then(() => {
79+
db.documents.write({
80+
uri: '/test/write_tlsV1.2.json',
81+
contentType: 'application/json',
82+
content: '{"key1":"Test"}'
83+
}).result(()=> done(new Error('Document write should fail when user uses 1.2 and server needs min TLS version as 1.3'))
84+
).catch(error=> {
85+
// TLS handshake error.
86+
error.message.should.containEql("SSL routines")
87+
done();
88+
})
89+
}).catch(error=> done(error));
90+
});
91+
92+
it('should write document with minVersion and maxVersion', function (done) {
93+
testconfig.restConnectionForTls.minVersion = 'TLSv1.2';
94+
testconfig.restConnectionForTls.maxVersion = 'TLSv1.3';
95+
db = marklogic.createDatabaseClient(testconfig.restConnectionForTls);
96+
updateTlsVersion('TLSv1.3').then(() => {
97+
db.documents.write({
98+
uri: '/test/write_with_min_and_max_versions.json',
99+
contentType: 'application/json',
100+
content: '{"key1":"With min and max TLS versions."}'
101+
}).result(() => done()).catch(error => {
102+
db.documents.read('/test/write_with_min_and_max_versions.json')
103+
.result(function (documents) {
104+
documents[0].content.should.have.property('key1');
105+
documents[0].content.key1.should.equal('With min and max TLS versions.');
106+
107+
}).then(() => done())
108+
.catch(error => done(error));
109+
}).catch(error=> done(error));
110+
}).catch(error=> done(error));
111+
});
112+
113+
it('should write document with only minVersion', function (done) {
114+
testconfig.restConnectionForTls.minVersion = 'TLSv1.2';
115+
db = marklogic.createDatabaseClient(testconfig.restConnectionForTls);
116+
updateTlsVersion('TLSv1.3').then(() => {
117+
db.documents.write({
118+
uri: '/test/write_with_only_min_version.json',
119+
contentType: 'application/json',
120+
content: '{"key1":"With only min TLS version."}'
121+
}).result(() => done()).catch(error => {
122+
db.documents.read('/test/write_with_only_min_version.json')
123+
.result(function (documents) {
124+
documents[0].content.should.have.property('key1');
125+
documents[0].content.key1.should.equal('With only min TLS version.');
126+
127+
}).then(() => done())
128+
.catch(error => done(error));
129+
}).catch(error=> done(error));
130+
}).catch(error=> done(error));
131+
});
132+
133+
it('should write document with only maxVersion', function (done) {
134+
testconfig.restConnectionForTls.maxVersion = 'TLSv1.3';
135+
db = marklogic.createDatabaseClient(testconfig.restConnectionForTls);
136+
updateTlsVersion('TLSv1.3').then(() => {
137+
db.documents.write({
138+
uri: '/test/write_with_only_max_version.json',
139+
contentType: 'application/json',
140+
content: '{"key1":"With only max TLS version."}'
141+
}).result(() => done()).catch(error => {
142+
db.documents.read('/test/write_with_only_max_version.json')
143+
.result(function (documents) {
144+
documents[0].content.should.have.property('key1');
145+
documents[0].content.key1.should.equal('With only max TLS version.');
146+
147+
}).then(() => done())
148+
.catch(error => done(error));
149+
}).catch(error=> done(error));
150+
}).catch(error=> done(error));
151+
});
152+
})
153+
154+
function updateTlsVersion(tlsVersion) {
155+
return new Promise((resolve, reject) => {
156+
const curlCommand = `
157+
curl --anyauth --user admin:admin -X PUT -H "Content-Type: application/json" \
158+
-d '{"ssl-min-allow-tls": "${tlsVersion}"}' \
159+
'http://${host}:8002/manage/v2/servers/unittest-nodeapi-ssl/properties?group-id=Default'
160+
`;
161+
exec(curlCommand, (error, stdout, stderr) => {
162+
if (error) {
163+
throw new Error(`Error executing curl: ${stderr}`);
164+
}
165+
resolve();
166+
});
167+
});
168+
}
169+

0 commit comments

Comments
 (0)