diff --git a/package-lock.json b/package-lock.json index f9736d35d41..1b13d25f9ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47138,6 +47138,30 @@ "typescript": "^5.9.3" } }, + "packages/atlas-service/node_modules/@mongodb-js/devtools-connect": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-connect/-/devtools-connect-3.12.0.tgz", + "integrity": "sha512-/aiGAKE5k6y1noI6hFo3pkLarNCNjEn+J3iqWTAMBuX4SpKUWsDdpMAyyxkqou7qH97gvon4A7wQafWFgWTXvA==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/devtools-proxy-support": "^0.5.5", + "@mongodb-js/oidc-http-server-pages": "1.1.8", + "lodash.merge": "^4.6.2", + "mongodb-connection-string-url": "^3.0.0", + "socks": "^2.7.3" + }, + "optionalDependencies": { + "kerberos": "^2.1.0", + "mongodb-client-encryption": "^6.1.0", + "os-dns-native": "^1.2.0", + "resolve-mongodb-srv": "^1.1.1" + }, + "peerDependencies": { + "@mongodb-js/oidc-plugin": "^2.0.0", + "mongodb": "^6.9.0", + "mongodb-log-writer": "^2.4.4" + } + }, "packages/atlas-service/node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -52697,6 +52721,30 @@ "mongodb-client-encryption": "^6.5.0" } }, + "packages/data-service/node_modules/@mongodb-js/devtools-connect": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-connect/-/devtools-connect-3.12.0.tgz", + "integrity": "sha512-/aiGAKE5k6y1noI6hFo3pkLarNCNjEn+J3iqWTAMBuX4SpKUWsDdpMAyyxkqou7qH97gvon4A7wQafWFgWTXvA==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/devtools-proxy-support": "^0.5.5", + "@mongodb-js/oidc-http-server-pages": "1.1.8", + "lodash.merge": "^4.6.2", + "mongodb-connection-string-url": "^3.0.0", + "socks": "^2.7.3" + }, + "optionalDependencies": { + "kerberos": "^2.1.0", + "mongodb-client-encryption": "^6.1.0", + "os-dns-native": "^1.2.0", + "resolve-mongodb-srv": "^1.1.1" + }, + "peerDependencies": { + "@mongodb-js/oidc-plugin": "^2.0.0", + "mongodb": "^6.9.0", + "mongodb-log-writer": "^2.4.4" + } + }, "packages/data-service/node_modules/@mongodb-js/devtools-docker-test-envs": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-docker-test-envs/-/devtools-docker-test-envs-1.3.3.tgz", @@ -52759,7 +52807,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/kerberos/-/kerberos-2.2.1.tgz", "integrity": "sha512-Vlyv1tjAPb0y2VIJ03dKkUjsneGIBuTkH24uGRx6/DrKpFlVuGPmct3m5aEotljVUlw7PAGWABwR5aNeW7y8Zw==", - "dev": true, + "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -52774,7 +52822,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", - "dev": true, + "devOptional": true, "license": "MIT" }, "packages/data-service/node_modules/sinon": { @@ -60990,6 +61038,22 @@ "typescript": "^5.9.3" }, "dependencies": { + "@mongodb-js/devtools-connect": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-connect/-/devtools-connect-3.12.0.tgz", + "integrity": "sha512-/aiGAKE5k6y1noI6hFo3pkLarNCNjEn+J3iqWTAMBuX4SpKUWsDdpMAyyxkqou7qH97gvon4A7wQafWFgWTXvA==", + "requires": { + "@mongodb-js/devtools-proxy-support": "^0.5.5", + "@mongodb-js/oidc-http-server-pages": "1.1.8", + "kerberos": "^2.1.0", + "lodash.merge": "^4.6.2", + "mongodb-client-encryption": "^6.1.0", + "mongodb-connection-string-url": "^3.0.0", + "os-dns-native": "^1.2.0", + "resolve-mongodb-srv": "^1.1.1", + "socks": "^2.7.3" + } + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -86048,6 +86112,22 @@ "typescript": "^5.9.3" }, "dependencies": { + "@mongodb-js/devtools-connect": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-connect/-/devtools-connect-3.12.0.tgz", + "integrity": "sha512-/aiGAKE5k6y1noI6hFo3pkLarNCNjEn+J3iqWTAMBuX4SpKUWsDdpMAyyxkqou7qH97gvon4A7wQafWFgWTXvA==", + "requires": { + "@mongodb-js/devtools-proxy-support": "^0.5.5", + "@mongodb-js/oidc-http-server-pages": "1.1.8", + "kerberos": "^2.1.0", + "lodash.merge": "^4.6.2", + "mongodb-client-encryption": "^6.1.0", + "mongodb-connection-string-url": "^3.0.0", + "os-dns-native": "^1.2.0", + "resolve-mongodb-srv": "^1.1.1", + "socks": "^2.7.3" + } + }, "@mongodb-js/devtools-docker-test-envs": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-docker-test-envs/-/devtools-docker-test-envs-1.3.3.tgz", @@ -86097,7 +86177,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/kerberos/-/kerberos-2.2.1.tgz", "integrity": "sha512-Vlyv1tjAPb0y2VIJ03dKkUjsneGIBuTkH24uGRx6/DrKpFlVuGPmct3m5aEotljVUlw7PAGWABwR5aNeW7y8Zw==", - "dev": true, + "devOptional": true, "requires": { "node-addon-api": "^6.1.0", "prebuild-install": "^7.1.2" @@ -86107,7 +86187,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", - "dev": true + "devOptional": true }, "sinon": { "version": "9.2.4", diff --git a/packages/compass-connections/src/components/connection-status-notifications.tsx b/packages/compass-connections/src/components/connection-status-notifications.tsx index a7682e54a15..af111174685 100644 --- a/packages/compass-connections/src/components/connection-status-notifications.tsx +++ b/packages/compass-connections/src/components/connection-status-notifications.tsx @@ -100,7 +100,14 @@ function ConnectionErrorToastBody({ > {info ? getConnectionTitle(info) : 'Connection failed'} - {error.message} + {info && onReview && ( diff --git a/packages/compass-connections/src/index.tsx b/packages/compass-connections/src/index.tsx index 60e2f2b79f6..7743a2cde3a 100644 --- a/packages/compass-connections/src/index.tsx +++ b/packages/compass-connections/src/index.tsx @@ -73,6 +73,11 @@ const ConnectionsComponent: React.FunctionComponent<{ * When connections fail to load, this callback will be called */ onFailToLoadConnections: (error: Error) => void; + /** + * Can be used to override the default useSystemCA behavior. + * Set to false in browser environments where system CA certificates are not available. + */ + useSystemCA?: boolean; }> = ({ children }) => { const activeConnections = useConnectionsList((connection) => { return connection.status === 'connected'; @@ -119,6 +124,7 @@ const CompassConnectionsPlugin = registerCompassPlugin( globalAppRegistry, onFailToLoadConnections: initialProps.onFailToLoadConnections, compassAssistant, + useSystemCA: initialProps.useSystemCA, }); setTimeout(() => { diff --git a/packages/compass-connections/src/stores/connections-store-redux.ts b/packages/compass-connections/src/stores/connections-store-redux.ts index 85db8197767..468b2489c85 100644 --- a/packages/compass-connections/src/stores/connections-store-redux.ts +++ b/packages/compass-connections/src/stores/connections-store-redux.ts @@ -214,6 +214,7 @@ type ThunkExtraArg = { globalAppRegistry: Pick; onFailToLoadConnections: (error: Error) => void; compassAssistant: CompassAssistantService; + useSystemCA?: boolean; }; export type ConnectionsThunkAction< @@ -1532,6 +1533,7 @@ const connectWithOptions = ( appName, getExtraConnectionData, connectFn, + useSystemCA, } ) => { let inflightConnection = InFlightConnections.get(connectionInfo.id); @@ -1643,6 +1645,7 @@ const connectWithOptions = ( deviceAuthAbortController.signal ); }, + useSystemCA, }), } ); diff --git a/packages/compass-e2e-tests/helpers/compass-web-sandbox.ts b/packages/compass-e2e-tests/helpers/compass-web-sandbox.ts index caccb9f9608..6b00e234dc6 100644 --- a/packages/compass-e2e-tests/helpers/compass-web-sandbox.ts +++ b/packages/compass-e2e-tests/helpers/compass-web-sandbox.ts @@ -208,7 +208,11 @@ export const getAtlasCloudSandboxDefaultConnections = ( str.password = dbPassword; return { id: name, - connectionOptions: { connectionString: String(str) }, + connectionOptions: { + connectionString: String(str), + // System CA certificates are not available in the browser environment + useSystemCA: false, + }, favorite: { name }, }; }); diff --git a/packages/compass-e2e-tests/helpers/compass.ts b/packages/compass-e2e-tests/helpers/compass.ts index a614354389a..b9bf35205d0 100644 --- a/packages/compass-e2e-tests/helpers/compass.ts +++ b/packages/compass-e2e-tests/helpers/compass.ts @@ -24,12 +24,14 @@ import { CHROME_STARTUP_FLAGS } from './chrome-startup-flags'; import { DEFAULT_CONNECTION_STRINGS, DEFAULT_CONNECTION_NAMES, + DEFAULT_CONNECTIONS, DEFAULT_CONNECTIONS_SERVER_INFO, isTestingWeb, isTestingDesktop, context, assertTestingWeb, isTestingAtlasCloudExternal, + isTestingAtlasCloudSandbox, } from './test-runner-context'; import { MONOREPO_ELECTRON_CHROMIUM_VERSION, @@ -897,6 +899,22 @@ export async function startBrowser( ); } else { await browser.navigateTo(context.sandboxUrl); + + // For Atlas Cloud Sandbox tests, inject the default connections into localStorage + // and reload the page so that SandboxConnectionStorage picks them up + if (isTestingAtlasCloudSandbox(context)) { + await browser.execute((connections) => { + const historyKey = 'CONNECTIONS_HISTORY_V$'; + const bytes = new TextEncoder().encode(JSON.stringify(connections)); + const binStr = String.fromCodePoint(...bytes); + const b64Str = window.btoa(binStr); + localStorage.setItem(historyKey, b64Str); + }, DEFAULT_CONNECTIONS); + + // Reload the page so that SandboxConnectionStorage is re-instantiated + // with the connections from localStorage + await browser.navigateTo(context.sandboxUrl); + } } const compass = new Compass(name, browser, { diff --git a/packages/compass-web/polyfills/@mongodb-js/devtools-connect/index.ts b/packages/compass-web/polyfills/@mongodb-js/devtools-connect/index.ts deleted file mode 100644 index 046692f9a4e..00000000000 --- a/packages/compass-web/polyfills/@mongodb-js/devtools-connect/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -export function hookLogger() { - /* no-op */ -} -export async function connectMongoClient( - url: string, - options: any, - logger: any, - MongoClient: any -): Promise { - // Remove options not understood by the plain Node.js driver - delete options.proxy; - delete options.applyProxyToOIDC; - delete options.productDocsLink; - delete options.productName; - delete options.oidc; - delete options.parentState; - delete options.parentHandle; - options.__skipPingOnConnect = true; - const client = new MongoClient(url, options); - await client.connect(); - return { - client, - state: { - getStateShareServer() { - return Promise.resolve('Not Available'); - }, - oidcPlugin: { - logger, - serialize() { - return Promise.resolve(undefined); - }, - }, - destroy() { - return Promise.resolve(); - }, - }, - }; -} diff --git a/packages/compass-web/polyfills/@mongodb-js/devtools-proxy-support/index.ts b/packages/compass-web/polyfills/@mongodb-js/devtools-proxy-support/index.ts index 33189348b98..b356c5a39c3 100644 --- a/packages/compass-web/polyfills/@mongodb-js/devtools-proxy-support/index.ts +++ b/packages/compass-web/polyfills/@mongodb-js/devtools-proxy-support/index.ts @@ -1,6 +1,9 @@ export function createAgent(): void { // The original can return 'undefined' as well } +export function isExistingAgentInstance(): boolean { + return false; +} export function useOrCreateAgent(): void { // The original can return 'undefined' as well } @@ -10,14 +13,17 @@ export function createSocks5Tunnel(): void { export function hookLogger(): void { // no-op } -export function createFetch(): never { - throw new Error('node-fetch like-API not available in compass-web'); +export function createFetch(): typeof fetch { + return async () => + Promise.reject(new Error('node-fetch not available in compass web')); } -export function systemCA(): never { - throw new Error('system CA access not available in compass-web'); +export async function systemCA() { + await Promise.reject( + new Error('system CA access not available in compass-web') + ); } export function resetSystemCACache(): never { - throw new Error('system CA access not available in compass-web'); + throw new Error('reset system CA access not available in compass-web'); } // Explicitly web-compatible diff --git a/packages/compass-web/polyfills/@mongodb-js/oidc-plugin/index.ts b/packages/compass-web/polyfills/@mongodb-js/oidc-plugin/index.ts new file mode 100644 index 00000000000..bfe64886334 --- /dev/null +++ b/packages/compass-web/polyfills/@mongodb-js/oidc-plugin/index.ts @@ -0,0 +1,10 @@ +export function hookLoggerToMongoLogWriter() {} +export function createMongoDBOIDCPlugin({ logger }: any) { + return { + mongoClientOptions: {}, + logger, + /* eslint-disable @typescript-eslint/require-await */ + serialize: async () => '', + destroy: () => {}, + }; +} diff --git a/packages/compass-web/polyfills/net/index.ts b/packages/compass-web/polyfills/net/index.ts index b1081232fbb..585fb99436f 100644 --- a/packages/compass-web/polyfills/net/index.ts +++ b/packages/compass-web/polyfills/net/index.ts @@ -27,8 +27,12 @@ class Socket extends Duplex { lookup?: ConnectionOptions['lookup']; tls?: boolean; }) { + // WS does not support callback lookup + if ((lookup?.length ?? 0) > 0) lookup = undefined; + const { wsURL, ...atlasOptions } = lookup?.() ?? ({} as { wsURL?: string; clusterName?: string }); + this._ws = new WebSocket(wsURL ?? '/ws-proxy'); this._ws.binaryType = 'arraybuffer'; this._ws.addEventListener( @@ -159,8 +163,6 @@ export { isIPv4, isIPv6 } from 'is-ip'; export const isIP = (input: string) => ipVersion(input) ?? 0; export const createConnection = (options: { host: string; port: number }) => { const socket = new Socket(); - setTimeout(() => { - socket.connect(options); - }); + socket.connect(options); return socket; }; diff --git a/packages/compass-web/polyfills/os-dns-native/index.ts b/packages/compass-web/polyfills/os-dns-native/index.ts new file mode 100644 index 00000000000..612046acb46 --- /dev/null +++ b/packages/compass-web/polyfills/os-dns-native/index.ts @@ -0,0 +1,7 @@ +import { resolveSrv, resolveTxt } from '../dns'; + +export const wasNativelyLookedUp = () => false; +export const withNodeFallback = { + resolveSrv, + resolveTxt, +}; diff --git a/packages/compass-web/sandbox/sandbox-connection-storage.tsx b/packages/compass-web/sandbox/sandbox-connection-storage.tsx index aae40bd3da4..beddeb6e40e 100644 --- a/packages/compass-web/sandbox/sandbox-connection-storage.tsx +++ b/packages/compass-web/sandbox/sandbox-connection-storage.tsx @@ -36,14 +36,36 @@ class SandboxConnectionStorage implements ConnectionStorage { return [info.id, info]; }) ); + + // Ensure useSystemCA is set to false for all connections since system CA + // certificates are not available in the browser environment + private normalizeConnectionInfo(info: ConnectionInfo): ConnectionInfo { + return { + ...info, + connectionOptions: { + ...info.connectionOptions, + useSystemCA: false, + }, + }; + } + loadAll(): Promise { - return Promise.resolve(Array.from(this._connections.values())); + return Promise.resolve( + Array.from(this._connections.values()).map((info) => + this.normalizeConnectionInfo(info) + ) + ); } load({ id }: { id: string }): Promise { - return Promise.resolve(this._connections.get(id)); + const info = this._connections.get(id); + return Promise.resolve( + info ? this.normalizeConnectionInfo(info) : undefined + ); } save({ connectionInfo }: { connectionInfo: ConnectionInfo }): Promise { - this._connections.set(connectionInfo.id, connectionInfo); + // Normalize the connection to ensure useSystemCA is false before saving + const normalizedInfo = this.normalizeConnectionInfo(connectionInfo); + this._connections.set(normalizedInfo.id, normalizedInfo); setTimeout(() => { saveHistory(Array.from(this._connections.values())); }, 0); diff --git a/packages/compass-web/src/connection-storage.tsx b/packages/compass-web/src/connection-storage.tsx index 5bc824d5c65..17b49352ac9 100644 --- a/packages/compass-web/src/connection-storage.tsx +++ b/packages/compass-web/src/connection-storage.tsx @@ -138,6 +138,7 @@ export class AtlasCloudConnectionStorage ...connectionInfo, connectionOptions: { ...connectionInfo.connectionOptions, + useSystemCA: false, lookup: () => { return { wsURL: this.atlasService.driverProxyEndpoint( @@ -162,6 +163,22 @@ export class AtlasCloudConnectionStorage }); return this.loadAllPromise; } + + async save({ + connectionInfo, + }: { + connectionInfo: ConnectionInfo; + }): Promise { + // Ensure useSystemCA is false for all connections in the browser environment + const normalizedInfo: ConnectionInfo = { + ...connectionInfo, + connectionOptions: { + ...connectionInfo.connectionOptions, + useSystemCA: false, + }, + }; + return super.save({ connectionInfo: normalizedInfo }); + } } const SandboxConnectionStorageContext = diff --git a/packages/compass-web/src/entrypoint.tsx b/packages/compass-web/src/entrypoint.tsx index b25363d3973..55545c1e7fa 100644 --- a/packages/compass-web/src/entrypoint.tsx +++ b/packages/compass-web/src/entrypoint.tsx @@ -126,6 +126,52 @@ const WithAtlasProviders: React.FC<{ children: React.ReactNode }> = ({ ); }; +const WithConnectionsProvider: React.FC<{ + appName: string; + autoconnectId?: string; + onFailToLoadConnections: (err: Error) => void; + children: React.ReactNode; +}> = ({ appName, autoconnectId, onFailToLoadConnections, children }) => { + const logger = useCompassWebLogger({}); + + return ( + { + return Promise.resolve([{}, null] as [Record, null]); + }} + onAutoconnectInfoRequest={(connectionStore) => { + if (autoconnectId) { + return connectionStore.loadAll().then( + (connections) => { + return connections.find( + (connectionInfo) => connectionInfo.id === autoconnectId + ); + }, + (err) => { + const { log, mongoLogId } = logger; + log.warn( + mongoLogId(1_001_000_329), + 'Compass Web', + 'Could not load connections when trying to autoconnect', + { err: err.message } + ); + return undefined; + } + ); + } + return Promise.resolve(undefined); + }} + > + {children} + + ); +}; + const WithStorageProviders = createServiceProvider( function WithStorageProviders({ orgId, @@ -556,38 +602,10 @@ const CompassWeb = ({ originForPrompt="atlas-data-explorer" appNameForPrompt={APP_NAMES_FOR_PROMPT.DataExplorer} > - { - return Promise.resolve([{}, null] as [ - Record, - null - ]); - }} - onAutoconnectInfoRequest={(connectionStore) => { - if (autoconnectId) { - return connectionStore.loadAll().then( - (connections) => { - return connections.find( - (connectionInfo) => - connectionInfo.id === autoconnectId - ); - }, - (err) => { - const { log, mongoLogId } = logger; - log.warn( - mongoLogId(1_001_000_329), - 'Compass Web', - 'Could not load connections when trying to autoconnect', - { err: err.message } - ); - return undefined; - } - ); - } - return Promise.resolve(undefined); - }} > @@ -611,7 +629,7 @@ const CompassWeb = ({ isCloudOptIn={true} /> - + diff --git a/packages/compass-web/webpack.config.js b/packages/compass-web/webpack.config.js index 8d63c2b2d75..9b358c16390 100644 --- a/packages/compass-web/webpack.config.js +++ b/packages/compass-web/webpack.config.js @@ -45,6 +45,7 @@ module.exports = (env, args) => { '@mongodb-js/devtools-proxy-support': localPolyfill( '@mongodb-js/devtools-proxy-support' ), + '@mongodb-js/oidc-plugin': localPolyfill('@mongodb-js/oidc-plugin'), ...(config.mode === 'production' ? { @@ -56,14 +57,6 @@ module.exports = (env, args) => { } : {}), - // Replace 'devtools-connect' with a package that just directly connects - // using the driver (= web-compatible driver) logic, because devtools-connect - // contains a lot of logic that makes sense in a desktop application/CLI but - // not in a web environment (DNS resolution, OIDC, CSFLE/QE, etc.) - '@mongodb-js/devtools-connect': localPolyfill( - '@mongodb-js/devtools-connect' - ), - // TODO(COMPASS-7407): compass-logging // hard to disable the whole thing while there are direct dependencies // on log-writer @@ -124,6 +117,7 @@ module.exports = (env, args) => { os: require.resolve('os-browserify/browser'), crypto: require.resolve('crypto-browserify'), dns: localPolyfill('dns'), + 'os-dns-native': localPolyfill('os-dns-native'), // Built-in Node.js modules imported by the driver directly and used in // ways that requires us to provide a no-op polyfill zlib: localPolyfill('zlib'), diff --git a/packages/connection-form/src/hooks/use-connect-form.ts b/packages/connection-form/src/hooks/use-connect-form.ts index 1f8c7a060b2..1571db2bec6 100644 --- a/packages/connection-form/src/hooks/use-connect-form.ts +++ b/packages/connection-form/src/hooks/use-connect-form.ts @@ -848,6 +848,7 @@ export function adjustConnectionOptionsBeforeConnect({ defaultAppName, notifyDeviceFlow, preferences, + useSystemCA, }: { connectionOptions: Readonly; connectionId: string; @@ -861,6 +862,7 @@ export function adjustConnectionOptionsBeforeConnect({ telemetryAnonymousId?: string; forceConnectionOptions: [string, string][]; }; + useSystemCA?: boolean; }): ConnectionOptions { const transformers: (( connectionOptions: Readonly @@ -882,5 +884,14 @@ export function adjustConnectionOptionsBeforeConnect({ for (const transformer of transformers) { connectionOptions = transformer(connectionOptions); } + + // Apply useSystemCA if explicitly provided + if (useSystemCA !== undefined) { + connectionOptions = { + ...connectionOptions, + useSystemCA, + }; + } + return connectionOptions; } diff --git a/packages/connection-storage/src/compass-main-connection-storage.spec.ts b/packages/connection-storage/src/compass-main-connection-storage.spec.ts index 3cb992a386d..d88700f5e69 100644 --- a/packages/connection-storage/src/compass-main-connection-storage.spec.ts +++ b/packages/connection-storage/src/compass-main-connection-storage.spec.ts @@ -795,6 +795,7 @@ describe('ConnectionStorage', function () { oidc: {}, fleOptions: { storeCredentials: false }, lookup: () => ({} as any), + useSystemCA: true, }; await connectionStorage.save({ connectionInfo: { diff --git a/packages/data-service/src/connect-mongo-client.spec.ts b/packages/data-service/src/connect-mongo-client.spec.ts index f5349d5634f..f6edb830f39 100644 --- a/packages/data-service/src/connect-mongo-client.spec.ts +++ b/packages/data-service/src/connect-mongo-client.spec.ts @@ -14,6 +14,7 @@ import ConnectionString from 'mongodb-connection-string-url'; const defaultOptions = { productDocsLink: 'https://www.mongodb.com/docs/compass/', productName: 'MongoDB Compass', + useSystemCA: true, }; const setupListeners = () => { diff --git a/packages/data-service/src/connect-mongo-client.ts b/packages/data-service/src/connect-mongo-client.ts index e3726a6dce0..9b3dc12cd19 100644 --- a/packages/data-service/src/connect-mongo-client.ts +++ b/packages/data-service/src/connect-mongo-client.ts @@ -164,6 +164,7 @@ export async function connectMongoClientDataService({ productDocsLink: productDocsLink ?? 'https://www.mongodb.com/docs/compass/', monitorCommands: true, autoEncryption: connectionOptions.fleOptions?.autoEncryption, + useSystemCA: connectionOptions.useSystemCA ?? true, ...oidcOptions, }; @@ -284,7 +285,17 @@ export async function connectMongoClientDataService({ const { client: metadataClient, state } = await connectSingleClient({ autoEncryption: undefined, }); - const parentHandlePromise = state.getStateShareServer(); + + // StateShareServer is only needed for OIDC authentication. + // Check if OIDC is being used before creating the server. + const connectionStringUrl = new ConnectionString(url); + const isOIDC = + connectionStringUrl.searchParams.get('authMechanism') === + 'MONGODB-OIDC'; + const parentHandlePromise = isOIDC + ? state.getStateShareServer() + : Promise.resolve(''); + parentHandlePromise.catch(() => { /* handled below */ }); @@ -323,7 +334,11 @@ export async function connectMongoClientDataService({ waitForTunnelError(tunnel), ]); // waitForTunnel always throws, never resolves - options.parentHandle = await state.getStateShareServer(); + // Only get StateShareServer handle for OIDC connections + const connectionStringUrl = new ConnectionString(url); + const isOIDC = + connectionStringUrl.searchParams.get('authMechanism') === 'MONGODB-OIDC'; + options.parentHandle = isOIDC ? await state.getStateShareServer() : ''; return [ metadataClient, diff --git a/packages/data-service/src/connection-options.ts b/packages/data-service/src/connection-options.ts index cc284f32fa5..d006dfce230 100644 --- a/packages/data-service/src/connection-options.ts +++ b/packages/data-service/src/connection-options.ts @@ -19,7 +19,8 @@ export type OIDCOptions = Omit< >[]; }; -export interface ConnectionOptions { +export interface ConnectionOptions + extends Pick { /** * The connection string to connect to the MongoDB instance including all options set by the user. */