1- import { buildMongoClientOptions , MongoDBConfig } from "../mongodb"
1+ import { promises as fs } from "fs"
2+ import { MongoClient } from "mongodb"
3+ import {
4+ buildMongoClientOptions ,
5+ MongoIntegration ,
6+ type MongoDBConfig ,
7+ } from "../mongodb"
28import { withEnv } from "../../environment"
39
410describe ( "MongoDB Integration" , ( ) => {
511 const baseConfig : MongoDBConfig = {
6- connectionString : "mongodb://localhost :27017" ,
12+ connectionString : "mongodb://example.com :27017" ,
713 db : "test" ,
814 tlsCertificateKeyFile : "/etc/passwd" ,
915 tlsCAFile : "/etc/shadow" ,
@@ -25,4 +31,115 @@ describe("MongoDB Integration", () => {
2531 } )
2632 } )
2733 } )
34+
35+ describe ( "connection string TLS file options" , ( ) => {
36+ const fileOptions = [ "tlsCAFile" , "tlsCertificateKeyFile" , "tlsCRLFile" ]
37+ const policyError =
38+ "MongoDB TLS file options are only supported on self-hosted installations"
39+
40+ it . each ( [
41+ { name : "mongodb with TLS" , scheme : "mongodb" , tls : "tls=true&" } ,
42+ { name : "mongodb with SSL alias" , scheme : "mongodb" , tls : "ssl=true&" } ,
43+ { name : "mongodb+srv with TLS" , scheme : "mongodb+srv" , tls : "tls=true&" } ,
44+ { name : "mongodb+srv with implicit TLS" , scheme : "mongodb+srv" , tls : "" } ,
45+ ] ) (
46+ "rejects normalized $name URI file options on cloud" ,
47+ async ( { scheme, tls } ) => {
48+ await withEnv ( { SELF_HOSTED : undefined } , async ( ) => {
49+ for ( const option of fileOptions ) {
50+ const encoded = [ ...option ]
51+ . map (
52+ character =>
53+ `%${ character . charCodeAt ( 0 ) . toString ( 16 ) . padStart ( 2 , "0" ) } `
54+ )
55+ . join ( "" )
56+ for ( const key of [ option , option . toUpperCase ( ) , encoded ] ) {
57+ const integration = new MongoIntegration ( {
58+ ...baseConfig ,
59+ connectionString : `${ scheme } ://example.com/test?${ tls } ${ key } =/file.pem` ,
60+ } )
61+ await expect ( integration . connect ( ) ) . rejects . toThrow ( policyError )
62+ }
63+ }
64+ } )
65+ }
66+ )
67+
68+ it ( "returns the usual verification failure without reading a file or connecting" , async ( ) => {
69+ const readFile = jest . spyOn ( fs , "readFile" )
70+ const connect = jest . spyOn ( MongoClient . prototype , "connect" )
71+ try {
72+ await withEnv ( { SELF_HOSTED : undefined } , async ( ) => {
73+ const integration = new MongoIntegration ( {
74+ ...baseConfig ,
75+ connectionString :
76+ "mongodb://example.com/?tls=true&tlsCertificateKeyFile=/file.pem" ,
77+ } )
78+ await expect ( integration . testConnection ( ) ) . resolves . toEqual ( {
79+ connected : false ,
80+ error : policyError ,
81+ } )
82+ } )
83+ expect ( readFile ) . not . toHaveBeenCalled ( )
84+ expect ( connect ) . not . toHaveBeenCalled ( )
85+ } finally {
86+ readFile . mockRestore ( )
87+ connect . mockRestore ( )
88+ }
89+ } )
90+
91+ it ( "preserves ordinary cloud URI settings" , async ( ) => {
92+ await withEnv ( { SELF_HOSTED : undefined } , async ( ) => {
93+ const integration = new MongoIntegration ( {
94+ ...baseConfig ,
95+ connectionString :
96+ "mongodb://example.com/test?tls=true&replicaSet=rs0&appName=tlsCAFile%3D%2Ffile.pem&readPreference=secondary" ,
97+ } )
98+
99+ expect ( integration [ "client" ] . options ) . toMatchObject ( {
100+ tls : true ,
101+ dbName : "test" ,
102+ replicaSet : "rs0" ,
103+ appName : "tlsCAFile=/file.pem" ,
104+ readPreference : { mode : "secondary" } ,
105+ } )
106+ expect ( integration [ "client" ] . options . tlsCAFile ) . toBeUndefined ( )
107+ expect (
108+ integration [ "client" ] . options . tlsCertificateKeyFile
109+ ) . toBeUndefined ( )
110+ expect ( integration [ "client" ] . options . tlsCRLFile ) . toBeUndefined ( )
111+
112+ const connect = jest
113+ . spyOn ( integration [ "client" ] , "connect" )
114+ . mockResolvedValue ( integration [ "client" ] )
115+ await integration . connect ( )
116+ expect ( connect ) . toHaveBeenCalledTimes ( 1 )
117+ } )
118+ } )
119+
120+ it ( "preserves self-hosted URI TLS file options" , async ( ) => {
121+ await withEnv ( { SELF_HOSTED : "true" } , async ( ) => {
122+ const integration = new MongoIntegration ( {
123+ ...baseConfig ,
124+ tlsCAFile : "" ,
125+ tlsCertificateKeyFile : "" ,
126+ connectionString :
127+ "mongodb://example.com/?tls=true&TLSCAFILE=/ca.pem&%74lsCertificateKeyFile=/key.pem&TlScRlFiLe=/crl.pem" ,
128+ } )
129+
130+ expect ( integration [ "client" ] . options ) . toMatchObject ( {
131+ tls : true ,
132+ tlsCAFile : "/ca.pem" ,
133+ tlsCertificateKeyFile : "/key.pem" ,
134+ tlsCRLFile : "/crl.pem" ,
135+ } )
136+
137+ const connect = jest
138+ . spyOn ( integration [ "client" ] , "connect" )
139+ . mockResolvedValue ( integration [ "client" ] )
140+ await integration . connect ( )
141+ expect ( connect ) . toHaveBeenCalledTimes ( 1 )
142+ } )
143+ } )
144+ } )
28145} )
0 commit comments