1- import { assert , expect } from 'chai' ;
1+ import { expect } from 'chai' ;
22import { promises as fs } from 'fs' ;
33import path from 'path' ;
44import { startTestServer } from '../../../testing/integration-testing-hooks' ;
@@ -20,6 +20,10 @@ const INVALID_CLIENT_CERT = getCertPath('invalid-client.bundle.pem');
2020const SERVER_KEY = getCertPath ( 'server.bundle.pem' ) ;
2121const SERVER_INVALIDHOST_KEY = getCertPath ( 'server-invalidhost.bundle.pem' ) ;
2222const CRL_INCLUDING_SERVER = getCertPath ( 'ca-server.crl' ) ;
23+ const PARTIAL_TRUST_CHAIN_CA = getCertPath ( 'partial-trust-chain/ca.pem' ) ;
24+ const PARTIAL_TRUST_CHAIN_KEY_AND_CERT = getCertPath (
25+ 'partial-trust-chain/key-and-cert.pem'
26+ ) ;
2327
2428/**
2529 * @securityTest TLS End-to-End Tests
@@ -35,13 +39,19 @@ describe('e2e TLS', function () {
3539 const tmpdir = useTmpdir ( ) ;
3640
3741 before ( async function ( ) {
38- assert ( ( await fs . stat ( CA_CERT ) ) . isFile ( ) ) ;
39- assert ( ( await fs . stat ( NON_CA_CERT ) ) . isFile ( ) ) ;
40- assert ( ( await fs . stat ( CLIENT_CERT ) ) . isFile ( ) ) ;
41- assert ( ( await fs . stat ( CLIENT_CERT_PFX ) ) . isFile ( ) ) ;
42- assert ( ( await fs . stat ( INVALID_CLIENT_CERT ) ) . isFile ( ) ) ;
43- assert ( ( await fs . stat ( SERVER_KEY ) ) . isFile ( ) ) ;
44- assert ( ( await fs . stat ( CRL_INCLUDING_SERVER ) ) . isFile ( ) ) ;
42+ for ( const file of [
43+ CA_CERT ,
44+ NON_CA_CERT ,
45+ CLIENT_CERT ,
46+ CLIENT_CERT_PFX ,
47+ INVALID_CLIENT_CERT ,
48+ SERVER_KEY ,
49+ CRL_INCLUDING_SERVER ,
50+ PARTIAL_TRUST_CHAIN_CA ,
51+ PARTIAL_TRUST_CHAIN_KEY_AND_CERT ,
52+ ] ) {
53+ expect ( ( await fs . stat ( file ) ) . isFile ( ) ) . to . be . true ;
54+ }
4555
4656 const homeInfo = setTemporaryHomeDirectory ( ) ;
4757 homedir = homeInfo . homedir ;
@@ -304,6 +314,77 @@ describe('e2e TLS', function () {
304314 }
305315 ) ;
306316
317+ // Certificate fixtures and general concept mirrors
318+ // https://github.com/nodejs/node/blob/1b3420274ea8d8cca339a1f10301d2e80f577c4c/test/parallel/test-tls-client-allow-partial-trust-chain.js
319+ // This basically tests that we pass allowPartialTrustChain: true in the TLS options
320+ context (
321+ 'connecting without client cert to server with only partial trust chain' ,
322+ function ( ) {
323+ before ( function ( ) {
324+ // TODO(MONGOSH-1898): Drop Node.js 16 entirely
325+ if ( process . version . startsWith ( 'v16.' ) ) return this . skip ( ) ;
326+ // The Windows crypto libraries don't accept the particular certificate setup here
327+ // ('CertAddCertificateContextToStore Failed The object or property already exists'),
328+ // so will not let us start a mongod server
329+ if ( process . platform === 'win32' ) return this . skip ( ) ;
330+ } ) ;
331+
332+ const server = startTestServer ( 'e2e-tls-partial-trust-chain' , {
333+ args : [
334+ '--tlsMode' ,
335+ 'requireTLS' ,
336+ '--tlsCertificateKeyFile' ,
337+ PARTIAL_TRUST_CHAIN_KEY_AND_CERT ,
338+ '--tlsAllowConnectionsWithoutCertificates' ,
339+ '--tlsCAFile' ,
340+ PARTIAL_TRUST_CHAIN_CA ,
341+ ] ,
342+ } ) ;
343+
344+ it ( 'works with matching CA (connection string)' , async function ( ) {
345+ const shell = this . startTestShell ( {
346+ args : [
347+ await connectionStringWithLocalhost ( server , {
348+ tls : 'true' ,
349+ tlsCAFile : PARTIAL_TRUST_CHAIN_KEY_AND_CERT ,
350+ tlsAllowInvalidHostnames : 'true' ,
351+ } ) ,
352+ ] ,
353+ } ) ;
354+ const result = await shell . waitForPromptOrExit ( ) ;
355+ expect ( result . state ) . to . equal ( 'prompt' ) ;
356+ } ) ;
357+
358+ it ( 'works with matching CA (system certs)' , async function ( ) {
359+ if ( process . platform !== 'linux' ) {
360+ return this . skip ( ) ;
361+ }
362+ await fs . mkdir ( path . join ( tmpdir . path , 'certs' ) , { recursive : true } ) ;
363+ await fs . copyFile (
364+ PARTIAL_TRUST_CHAIN_CA ,
365+ path . join ( tmpdir . path , 'certs' , 'somefilename.crt' )
366+ ) ;
367+
368+ const shell = this . startTestShell ( {
369+ args : [
370+ await connectionStringWithLocalhost ( server , {
371+ serverSelectionTimeoutMS : '1500' ,
372+ tlsAllowInvalidHostnames : 'true' ,
373+ } ) ,
374+ '--tls' ,
375+ ] ,
376+ env : {
377+ ...env ,
378+ SSL_CERT_FILE : path . join ( tmpdir . path , 'certs' , 'somefilename.crt' ) ,
379+ } ,
380+ } ) ;
381+
382+ const prompt = await shell . waitForPromptOrExit ( ) ;
383+ expect ( prompt . state ) . to . equal ( 'prompt' ) ;
384+ } ) ;
385+ }
386+ ) ;
387+
307388 context ( 'connecting with client cert to server with valid cert' , function ( ) {
308389 after ( async function ( ) {
309390 const shell = this . startTestShell ( {
0 commit comments