From 8401a739cf2c56947bfff324a1c063c61e412bf6 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Wed, 14 Aug 2024 11:37:23 +0200 Subject: [PATCH] feat: add proxy support MONGOSH-1827 (#2123) This PR mostly just adds tests on top of the work done in devtools-shared. --- package-lock.json | 757 +++++++----------- packages/arg-parser/package.json | 2 +- packages/cli-repl/.depcheckrc | 3 +- packages/cli-repl/package.json | 2 +- packages/cli-repl/src/cli-repl.ts | 22 +- packages/cli-repl/src/run.ts | 7 + packages/e2e-tests/package.json | 1 + packages/e2e-tests/test/e2e-oidc.spec.ts | 27 +- packages/e2e-tests/test/e2e-proxy.spec.ts | 637 +++++++++++++++ packages/e2e-tests/test/e2e-snapshot.spec.ts | 4 +- packages/e2e-tests/test/e2e-tls.spec.ts | 26 +- packages/e2e-tests/test/oidc-helpers.ts | 20 + packages/e2e-tests/test/repl-helpers.ts | 18 + packages/e2e-tests/test/test-shell.ts | 11 + packages/logging/package.json | 2 +- packages/service-provider-server/package.json | 2 +- packages/types/package.json | 2 +- 17 files changed, 1015 insertions(+), 528 deletions(-) create mode 100644 packages/e2e-tests/test/e2e-proxy.spec.ts create mode 100644 packages/e2e-tests/test/oidc-helpers.ts diff --git a/package-lock.json b/package-lock.json index d06aa1013..0f35a021f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6544,12 +6544,12 @@ } }, "node_modules/@mongodb-js/devtools-connect": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-connect/-/devtools-connect-3.2.2.tgz", - "integrity": "sha512-0d/9hiNnVxFjgu0HtbUSMOem/hMtpj7aKj/QN3UsABGJ8jBxMXzE90jNP6JOJ+Nt5dmlCX2iTMvtJiBIWOtCZA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-connect/-/devtools-connect-3.2.4.tgz", + "integrity": "sha512-X904ayaza7LRoVbvNbSYJhFYxMrik+9uUcoLvgxHsEaxRWzubl0qqFz1+W4otKFNMJknzbkzjXSb24romTfsZg==", "license": "Apache-2.0", "dependencies": { - "@mongodb-js/devtools-proxy-support": "^0.3.2", + "@mongodb-js/devtools-proxy-support": "^0.3.4", "@mongodb-js/oidc-http-server-pages": "1.1.2", "lodash.merge": "^4.6.2", "mongodb-connection-string-url": "^3.0.0", @@ -6576,35 +6576,24 @@ } }, "node_modules/@mongodb-js/devtools-proxy-support": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-proxy-support/-/devtools-proxy-support-0.3.2.tgz", - "integrity": "sha512-qMSe/5XVEK3xXtMhtv+InIRuanH5nDdDo8yD3gFvsw5pRhI9qM5m06imfgx9X1woAFdntIUNy72lGNi2glbOaA==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-proxy-support/-/devtools-proxy-support-0.3.4.tgz", + "integrity": "sha512-+KqoTzqLdA0MOpaqxJH6VDWzsHEWLnt1GFfuaFrGmJLUgU7sC1QEP8la61eOAC4fR1W6S86ipZZaQNdJbrXWVw==", "license": "Apache-2.0", "dependencies": { "@mongodb-js/socksv5": "^0.0.10", "agent-base": "^7.1.1", + "debug": "^4.3.6", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.5", "lru-cache": "^11.0.0", "node-fetch": "^3.3.2", - "pac-proxy-agent": "7.0.2", + "pac-proxy-agent": "^7.0.2", "socks-proxy-agent": "^8.0.4", "ssh2": "^1.15.0", "system-ca": "^2.0.0" } }, - "node_modules/@mongodb-js/devtools-proxy-support/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/@mongodb-js/devtools-proxy-support/node_modules/data-uri-to-buffer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", @@ -6614,30 +6603,21 @@ "node": ">= 12" } }, - "node_modules/@mongodb-js/devtools-proxy-support/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "node_modules/@mongodb-js/devtools-proxy-support/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "license": "MIT", "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" + "ms": "2.1.2" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/@mongodb-js/devtools-proxy-support/node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" + "node": ">=6.0" }, - "engines": { - "node": ">= 14" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/@mongodb-js/devtools-proxy-support/node_modules/lru-cache": { @@ -6667,20 +6647,6 @@ "url": "https://opencollective.com/node-fetch" } }, - "node_modules/@mongodb-js/devtools-proxy-support/node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/@mongodb-js/dl-center": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@mongodb-js/dl-center/-/dl-center-1.1.1.tgz", @@ -8828,18 +8794,6 @@ "node": ">=16.3.0" } }, - "node_modules/@puppeteer/browsers/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/@puppeteer/browsers/node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -8854,32 +8808,6 @@ "node": ">=12" } }, - "node_modules/@puppeteer/browsers/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@puppeteer/browsers/node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/@puppeteer/browsers/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -8908,20 +8836,6 @@ "node": ">= 14" } }, - "node_modules/@puppeteer/browsers/node_modules/socks-proxy-agent": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz", - "integrity": "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.7.1" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/@puppeteer/browsers/node_modules/tar-fs": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", @@ -11459,14 +11373,14 @@ "optional": true }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dependencies": { - "debug": "4" + "debug": "^4.3.4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/agentkeepalive": { @@ -17993,16 +17907,15 @@ } }, "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/http-proxy-middleware": { @@ -18086,15 +17999,15 @@ "dev": true }, "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dependencies": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/human-signals": { @@ -22161,6 +22074,18 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/make-fetch-happen/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/make-fetch-happen/node_modules/cacache": { "version": "17.1.4", "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", @@ -22214,6 +22139,33 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "optional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/make-fetch-happen/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -22258,6 +22210,20 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/make-fetch-happen/node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/make-fetch-happen/node_modules/ssri": { "version": "10.0.5", "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", @@ -23576,6 +23542,17 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/node-gyp/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/node-gyp/node_modules/cacache": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.0.3.tgz", @@ -23623,6 +23600,31 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/node-gyp/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/node-gyp/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/node-gyp/node_modules/lru-cache": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.7.3.tgz", @@ -24829,7 +24831,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", - "license": "MIT", "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.0.2", @@ -24844,56 +24845,6 @@ "node": ">= 14" } }, - "node_modules/pac-proxy-agent/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/pac-resolver": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", @@ -24963,6 +24914,18 @@ "node": ">= 6" } }, + "node_modules/pacote/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/pacote/node_modules/http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", @@ -24977,6 +24940,19 @@ "node": ">= 6" } }, + "node_modules/pacote/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/pacote/node_modules/make-fetch-happen": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", @@ -25829,84 +25805,11 @@ "node": ">= 0.10" } }, - "node_modules/proxy-agent": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", - "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.3", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/proxy-agent/node_modules/socks-proxy-agent": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz", - "integrity": "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==", - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.7.1" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "devOptional": true }, "node_modules/prr": { "version": "1.0.1", @@ -28022,17 +27925,16 @@ } }, "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "optional": true, + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" }, "engines": { - "node": ">= 10" + "node": ">= 14" } }, "node_modules/sort-keys": { @@ -31003,7 +30905,7 @@ "mongodb-connection-string-url": "^3.0.1" }, "devDependencies": { - "@mongodb-js/devtools-connect": "^3.2.2", + "@mongodb-js/devtools-connect": "^3.2.4", "@mongodb-js/eslint-config-mongosh": "^1.0.0", "@mongodb-js/prettier-config-devtools": "^1.0.1", "@mongodb-js/tsconfig-mongosh": "^1.0.0", @@ -31335,6 +31237,7 @@ "version": "0.0.0-dev.0", "license": "Apache-2.0", "dependencies": { + "@mongodb-js/devtools-proxy-support": "^0.3.4", "@mongosh/arg-parser": "0.0.0-dev.0", "@mongosh/autocomplete": "0.0.0-dev.0", "@mongosh/editor": "0.0.0-dev.0", @@ -31361,7 +31264,6 @@ "mongodb-log-writer": "^1.4.2", "numeral": "^2.0.6", "pretty-repl": "^4.0.1", - "proxy-agent": "^6.4.0", "semver": "^7.5.4", "strip-ansi": "^6.0.0", "text-table": "^0.2.0", @@ -31442,6 +31344,7 @@ "@types/chai-as-promised": "^7.1.3", "@types/node": "^14.14.6", "@types/rimraf": "^3.0.0", + "bson": "^6.7.0", "chai-as-promised": "^7.1.1", "depcheck": "^1.4.3", "eslint": "^7.25.0", @@ -31750,7 +31653,7 @@ "version": "0.0.0-dev.0", "license": "Apache-2.0", "dependencies": { - "@mongodb-js/devtools-connect": "^3.2.2", + "@mongodb-js/devtools-connect": "^3.2.4", "@mongosh/errors": "0.0.0-dev.0", "@mongosh/history": "0.0.0-dev.0", "@mongosh/types": "0.0.0-dev.0", @@ -31842,7 +31745,7 @@ "version": "0.0.0-dev.0", "license": "Apache-2.0", "dependencies": { - "@mongodb-js/devtools-connect": "^3.2.2", + "@mongodb-js/devtools-connect": "^3.2.4", "@mongodb-js/oidc-plugin": "^1.1.1", "@mongosh/errors": "0.0.0-dev.0", "@mongosh/service-provider-core": "0.0.0-dev.0", @@ -31955,7 +31858,7 @@ "version": "0.0.0-dev.0", "license": "Apache-2.0", "dependencies": { - "@mongodb-js/devtools-connect": "^3.2.2" + "@mongodb-js/devtools-connect": "^3.2.4" }, "devDependencies": { "@mongodb-js/eslint-config-mongosh": "^1.0.0", @@ -37121,11 +37024,11 @@ } }, "@mongodb-js/devtools-connect": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-connect/-/devtools-connect-3.2.2.tgz", - "integrity": "sha512-0d/9hiNnVxFjgu0HtbUSMOem/hMtpj7aKj/QN3UsABGJ8jBxMXzE90jNP6JOJ+Nt5dmlCX2iTMvtJiBIWOtCZA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-connect/-/devtools-connect-3.2.4.tgz", + "integrity": "sha512-X904ayaza7LRoVbvNbSYJhFYxMrik+9uUcoLvgxHsEaxRWzubl0qqFz1+W4otKFNMJknzbkzjXSb24romTfsZg==", "requires": { - "@mongodb-js/devtools-proxy-support": "^0.3.2", + "@mongodb-js/devtools-proxy-support": "^0.3.4", "@mongodb-js/oidc-http-server-pages": "1.1.2", "kerberos": "^2.1.0", "lodash.merge": "^4.6.2", @@ -37142,51 +37045,34 @@ "integrity": "sha512-rBwJHZ0g3Ma6zluNUWfeFXvuxsz9ZtFX2YZ1qR/aQEwk64ZhOqjrVbcROSdtfGUs4qg1JGXFIU+ZQ+oLYqPEvQ==" }, "@mongodb-js/devtools-proxy-support": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-proxy-support/-/devtools-proxy-support-0.3.2.tgz", - "integrity": "sha512-qMSe/5XVEK3xXtMhtv+InIRuanH5nDdDo8yD3gFvsw5pRhI9qM5m06imfgx9X1woAFdntIUNy72lGNi2glbOaA==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-proxy-support/-/devtools-proxy-support-0.3.4.tgz", + "integrity": "sha512-+KqoTzqLdA0MOpaqxJH6VDWzsHEWLnt1GFfuaFrGmJLUgU7sC1QEP8la61eOAC4fR1W6S86ipZZaQNdJbrXWVw==", "requires": { "@mongodb-js/socksv5": "^0.0.10", "agent-base": "^7.1.1", + "debug": "^4.3.6", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.5", "lru-cache": "^11.0.0", "node-fetch": "^3.3.2", - "pac-proxy-agent": "7.0.2", + "pac-proxy-agent": "^7.0.2", "socks-proxy-agent": "^8.0.4", "ssh2": "^1.15.0", "system-ca": "^2.0.0" }, "dependencies": { - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "requires": { - "debug": "^4.3.4" - } - }, "data-uri-to-buffer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "requires": { - "agent-base": "^7.0.2", - "debug": "4" + "ms": "2.1.2" } }, "lru-cache": { @@ -37203,16 +37089,6 @@ "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } - }, - "socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "requires": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - } } } }, @@ -37597,7 +37473,7 @@ "@mongosh/arg-parser": { "version": "file:packages/arg-parser", "requires": { - "@mongodb-js/devtools-connect": "^3.2.2", + "@mongodb-js/devtools-connect": "^3.2.4", "@mongodb-js/eslint-config-mongosh": "^1.0.0", "@mongodb-js/prettier-config-devtools": "^1.0.1", "@mongodb-js/tsconfig-mongosh": "^1.0.0", @@ -37847,6 +37723,7 @@ "@mongosh/cli-repl": { "version": "file:packages/cli-repl", "requires": { + "@mongodb-js/devtools-proxy-support": "^0.3.4", "@mongodb-js/eslint-config-mongosh": "^1.0.0", "@mongodb-js/prettier-config-devtools": "^1.0.1", "@mongodb-js/sbom-tools": "^0.7.0", @@ -37894,7 +37771,6 @@ "numeral": "^2.0.6", "prettier": "^2.8.8", "pretty-repl": "^4.0.1", - "proxy-agent": "^6.4.0", "semver": "^7.5.4", "strip-ansi": "^6.0.0", "text-table": "^0.2.0", @@ -37942,6 +37818,7 @@ "@types/chai-as-promised": "^7.1.3", "@types/node": "^14.14.6", "@types/rimraf": "^3.0.0", + "bson": "^6.7.0", "chai-as-promised": "^7.1.1", "depcheck": "^1.4.3", "eslint": "^7.25.0", @@ -38137,7 +38014,7 @@ "@mongosh/logging": { "version": "file:packages/logging", "requires": { - "@mongodb-js/devtools-connect": "^3.2.2", + "@mongodb-js/devtools-connect": "^3.2.4", "@mongodb-js/eslint-config-mongosh": "^1.0.0", "@mongodb-js/prettier-config-devtools": "^1.0.1", "@mongodb-js/tsconfig-mongosh": "^1.0.0", @@ -38193,7 +38070,7 @@ "@mongosh/service-provider-server": { "version": "file:packages/service-provider-server", "requires": { - "@mongodb-js/devtools-connect": "^3.2.2", + "@mongodb-js/devtools-connect": "^3.2.4", "@mongodb-js/eslint-config-mongosh": "^1.0.0", "@mongodb-js/oidc-plugin": "^1.1.1", "@mongodb-js/prettier-config-devtools": "^1.0.1", @@ -38276,7 +38153,7 @@ "@mongosh/types": { "version": "file:packages/types", "requires": { - "@mongodb-js/devtools-connect": "^3.2.2", + "@mongodb-js/devtools-connect": "^3.2.4", "@mongodb-js/eslint-config-mongosh": "^1.0.0", "@mongodb-js/prettier-config-devtools": "^1.0.1", "@mongodb-js/tsconfig-mongosh": "^1.0.0", @@ -39463,15 +39340,6 @@ "yargs": "17.7.1" }, "dependencies": { - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - }, "cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -39483,26 +39351,6 @@ "wrap-ansi": "^7.0.0" } }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, "lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -39525,17 +39373,6 @@ "socks-proxy-agent": "^8.0.1" } }, - "socks-proxy-agent": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz", - "integrity": "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==", - "dev": true, - "requires": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.7.1" - } - }, "tar-fs": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", @@ -41777,11 +41614,11 @@ "optional": true }, "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "requires": { - "debug": "4" + "debug": "^4.3.4" } }, "agentkeepalive": { @@ -46811,13 +46648,12 @@ } }, "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" } }, "http-proxy-middleware": { @@ -46875,11 +46711,11 @@ "dev": true }, "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "requires": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" } }, @@ -50001,6 +49837,15 @@ "semver": "^7.3.5" } }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "requires": { + "debug": "4" + } + }, "cacache": { "version": "17.1.4", "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", @@ -50046,6 +49891,27 @@ } } }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "optional": true, + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -50078,6 +49944,17 @@ } } }, + "socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "optional": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + } + }, "ssri": { "version": "10.0.5", "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", @@ -51093,6 +50970,14 @@ "semver": "^7.3.5" } }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, "cacache": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.0.3.tgz", @@ -51131,6 +51016,25 @@ "path-is-absolute": "^1.0.0" } }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "lru-cache": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.7.3.tgz", @@ -52039,44 +51943,6 @@ "https-proxy-agent": "^7.0.5", "pac-resolver": "^7.0.1", "socks-proxy-agent": "^8.0.4" - }, - "dependencies": { - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "requires": { - "debug": "^4.3.4" - } - }, - "http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, - "socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "requires": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - } - } } }, "pac-resolver": { @@ -52133,6 +51999,15 @@ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", @@ -52144,6 +52019,16 @@ "debug": "4" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "make-fetch-happen": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", @@ -52798,68 +52683,11 @@ } } }, - "proxy-agent": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", - "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", - "requires": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.3", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" - }, - "dependencies": { - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "requires": { - "debug": "^4.3.4" - } - }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" - }, - "socks-proxy-agent": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz", - "integrity": "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==", - "requires": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.7.1" - } - } - } - }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "devOptional": true }, "prr": { "version": "1.0.1", @@ -54502,14 +54330,13 @@ } }, "socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "optional": true, + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" } }, "sort-keys": { diff --git a/packages/arg-parser/package.json b/packages/arg-parser/package.json index 546c2e27a..81d025ea3 100644 --- a/packages/arg-parser/package.json +++ b/packages/arg-parser/package.json @@ -40,7 +40,7 @@ "mongodb-connection-string-url": "^3.0.1" }, "devDependencies": { - "@mongodb-js/devtools-connect": "^3.2.2", + "@mongodb-js/devtools-connect": "^3.2.4", "@mongodb-js/eslint-config-mongosh": "^1.0.0", "@mongodb-js/prettier-config-devtools": "^1.0.1", "@mongodb-js/tsconfig-mongosh": "^1.0.0", diff --git a/packages/cli-repl/.depcheckrc b/packages/cli-repl/.depcheckrc index 4b084fde4..e3286fbd1 100644 --- a/packages/cli-repl/.depcheckrc +++ b/packages/cli-repl/.depcheckrc @@ -17,5 +17,6 @@ ignores: - emphasize - ipv6-normalize - bindings + - system-ca ignore-patterns: - - .eslintrc.js \ No newline at end of file + - .eslintrc.js diff --git a/packages/cli-repl/package.json b/packages/cli-repl/package.json index 2435d2b0f..2abfebae0 100644 --- a/packages/cli-repl/package.json +++ b/packages/cli-repl/package.json @@ -61,6 +61,7 @@ } }, "dependencies": { + "@mongodb-js/devtools-proxy-support": "^0.3.4", "@mongosh/arg-parser": "0.0.0-dev.0", "@mongosh/autocomplete": "0.0.0-dev.0", "@mongosh/editor": "0.0.0-dev.0", @@ -87,7 +88,6 @@ "mongodb-log-writer": "^1.4.2", "numeral": "^2.0.6", "pretty-repl": "^4.0.1", - "proxy-agent": "^6.4.0", "semver": "^7.5.4", "strip-ansi": "^6.0.0", "text-table": "^0.2.0", diff --git a/packages/cli-repl/src/cli-repl.ts b/packages/cli-repl/src/cli-repl.ts index cd75f9d55..8417ca16d 100644 --- a/packages/cli-repl/src/cli-repl.ts +++ b/packages/cli-repl/src/cli-repl.ts @@ -1174,24 +1174,10 @@ export class CliRepl implements MongoshIOProvider { )}\nWaiting...\n` ); }; - if (process.env.MONGOSH_EXPERIMENTAL_OIDC_PROXY_SUPPORT) { - const ProxyAgent = (await import('proxy-agent')).ProxyAgent; - const tlsCAFile = - driverOptions.tlsCAFile ?? - new ConnectionString(driverUri) - .typedSearchParams() - .get('tlsCAFile'); - const ca = tlsCAFile ? await fs.readFile(tlsCAFile) : undefined; - driverOptions.oidc.customHttpOptions = (_url, opts) => { - if (ca && !opts.ca) { - opts = { ...opts, ca }; - } - return { - ...opts, - agent: new ProxyAgent({ ...opts }), - }; - }; - } + driverOptions.proxy ??= { + useEnvironmentVariableProxies: true, + }; + driverOptions.applyProxyToOIDC ??= true; const [redirectURI, trustedEndpoints, browser] = await Promise.all([ this.getConfig('oidcRedirectURI'), diff --git a/packages/cli-repl/src/run.ts b/packages/cli-repl/src/run.ts index 69605e9a9..de9035ae0 100644 --- a/packages/cli-repl/src/run.ts +++ b/packages/cli-repl/src/run.ts @@ -31,6 +31,7 @@ import net from 'net'; import v8 from 'v8'; import { TimingCategories } from '@mongosh/types'; import './webpack-self-inspection'; +import { systemCA } from '@mongodb-js/devtools-proxy-support'; // TS does not yet have type definitions for v8.startupSnapshot if ((v8 as any)?.startupSnapshot?.isBuildingSnapshot?.()) { @@ -41,6 +42,7 @@ if ((v8 as any)?.startupSnapshot?.isBuildingSnapshot?.()) { require('emphasize'); // Dependency of pretty-repl require('ipv6-normalize'); // Dependency of devtools-connect via os-dns-native require('bindings'); // Used by various native dependencies but not a native dep itself + require('system-ca'); // Dependency of devtools-proxy-support { const console = require('console'); @@ -195,6 +197,11 @@ async function main() { } } + markTime(TimingCategories.Main, 'scheduling system-ca loading'); + // asynchronously populate the system CA cache in devtools-proxy-support + systemCA().catch(() => undefined); + markTime(TimingCategories.Main, 'scheduled system-ca loading'); + const connectionInfo = generateConnectionInfoFromCliArgs(options); connectionInfo.driverOptions = { ...connectionInfo.driverOptions, diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 8665d10d4..50245b6c2 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -39,6 +39,7 @@ "@types/chai-as-promised": "^7.1.3", "@types/node": "^14.14.6", "@types/rimraf": "^3.0.0", + "bson": "^6.7.0", "chai-as-promised": "^7.1.1", "depcheck": "^1.4.3", "eslint": "^7.25.0", diff --git a/packages/e2e-tests/test/e2e-oidc.spec.ts b/packages/e2e-tests/test/e2e-oidc.spec.ts index 5fd7b693b..0c38fe231 100644 --- a/packages/e2e-tests/test/e2e-oidc.spec.ts +++ b/packages/e2e-tests/test/e2e-oidc.spec.ts @@ -11,6 +11,11 @@ import path from 'path'; import { expect } from 'chai'; import { createServer as createHTTPSServer } from 'https'; import { getCertPath, useTmpdir } from './repl-helpers'; +import { + baseOidcServerConfig, + commonOidcServerArgs, + skipOIDCTestsDueToPlatformOrServerVersion, +} from './oidc-helpers'; /** * @securityTest OIDC Authentication End-to-End Tests @@ -47,17 +52,10 @@ describe('OIDC auth e2e', function () { skipIfEnvServerVersion('< 7.0'); before(async function () { - if ( - process.platform !== 'linux' || - !process.env.MONGOSH_SERVER_TEST_VERSION || - !process.env.MONGOSH_SERVER_TEST_VERSION.includes('-enterprise') || - +process.version.slice(1).split('.')[0] < 16 - ) { + if (skipOIDCTestsDueToPlatformOrServerVersion()) { // OIDC is only supported on Linux in the 7.0+ enterprise server, // and we can't skip based on the dynamically detected server version because // the OIDC config is something that needs to be available at server startup time. - // Our mock OIDC provider does not work with Node.js 14, so we also need to skip - // tests there. return this.skip(); } @@ -87,19 +85,8 @@ describe('OIDC auth e2e', function () { ]); const serverOidcConfig = { issuer: oidcMockProvider.issuer, - clientId: 'testServer', - requestScopes: ['mongodbGroups'], - authorizationClaim: 'groups', - audience: 'resource-server-audience-value', - authNamePrefix: 'dev', + ...baseOidcServerConfig, }; - const commonOidcServerArgs = [ - '--setParameter', - 'authenticationMechanisms=SCRAM-SHA-256,MONGODB-OIDC', - // enableTestCommands allows using http:// issuers such as http://localhost - '--setParameter', - 'enableTestCommands=true', - ]; testServer = new MongoRunnerSetup('e2e-oidc-test1', { args: [ '--setParameter', diff --git a/packages/e2e-tests/test/e2e-proxy.spec.ts b/packages/e2e-tests/test/e2e-proxy.spec.ts new file mode 100644 index 000000000..3e2b5a6a0 --- /dev/null +++ b/packages/e2e-tests/test/e2e-proxy.spec.ts @@ -0,0 +1,637 @@ +import type { + Server as HTTPServer, + IncomingMessage, + ServerResponse, +} from 'http'; +import { createServer as createHTTPServer, request } from 'http'; +import { + MongoRunnerSetup, + skipIfApiStrict, + skipIfEnvServerVersion, + startSharedTestServer, + startTestServer, +} from '../../../testing/integration-testing-hooks'; +import { TestShell } from './test-shell'; +import type { Server as HTTPSServer } from 'https'; +import { createServer as createHTTPSServer } from 'https'; +import { + connectionStringWithLocalhost, + getCertPath, + useTmpdir, +} from './repl-helpers'; +import { once } from 'events'; +import { connect } from 'net'; +import type { AddressInfo, Socket } from 'net'; +import { promises as fs } from 'fs'; +import { expect } from 'chai'; +import path from 'path'; +import type { OIDCMockProviderConfig } from '@mongodb-js/oidc-mock-provider'; +import { OIDCMockProvider } from '@mongodb-js/oidc-mock-provider'; +import { + baseOidcServerConfig, + commonOidcServerArgs, + skipOIDCTestsDueToPlatformOrServerVersion, +} from './oidc-helpers'; + +const CA_CERT = getCertPath('ca.crt'); +const SERVER_BUNDLE = getCertPath('server.bundle.pem'); + +describe('e2e proxy support', function () { + skipIfApiStrict(); + skipIfEnvServerVersion('< 7.0'); + + afterEach(TestShell.cleanup); + + const tmpdir = useTmpdir(); + const testServer = startSharedTestServer(); + + let httpServer: HTTPServer; + let httpsServer: HTTPSServer; + let connectRequests: IncomingMessage[]; + let httpForwardRequests: IncomingMessage[]; + let connections: Socket[]; + let allConnectionIds: () => string[]; + + beforeEach(async function () { + connectRequests = []; + httpForwardRequests = []; + connections = []; + allConnectionIds = () => + connections.flatMap((sock) => { + const { port } = sock.address() as AddressInfo; + return [`127.0.0.1:${port}`, `[::1]:${port}`, `localhost:${port}`]; + }); + + httpServer = createHTTPServer().listen(0); + await once(httpServer, 'listening'); + httpsServer = createHTTPSServer({ + key: await fs.readFile(SERVER_BUNDLE), + cert: await fs.readFile(SERVER_BUNDLE), + }).listen(0); + await once(httpsServer, 'listening'); + + httpServer.on('connect', onconnect); + httpServer.on('request', onrequest); + httpsServer.on('connect', onconnect); + httpsServer.on('request', onrequest); + function onconnect( + this: HTTPServer, + req: IncomingMessage, + socket: Socket, + head: Buffer + ) { + (req as any).server = this; + connectRequests.push(req); + socket.unshift(head); + socket.write('HTTP/1.0 200 OK\r\n\r\n'); + let host: string; + let port: string; + if (req.url?.includes(']:')) { + [host, port] = req.url.slice(1).split(']:'); + } else { + [host, port] = (req.url ?? '').split(':'); + } + const outbound = connect(+port, host); + socket.pipe(outbound).pipe(socket); + // socket.on('data', chk => console.log('[from client] ' + chk.toString())); + // outbound.on('data', chk => console.log('[from server] ' + chk.toString())); + const cleanup = () => { + outbound.destroy(); + socket.destroy(); + }; + outbound.on('error', cleanup); + socket.on('error', cleanup); + connections.push(socket, outbound); + } + function onrequest(req: IncomingMessage, res: ServerResponse) { + httpForwardRequests.push(req); + const proxyReq = request( + req.url!, + { method: req.method, headers: req.headers }, + (proxyRes) => proxyRes.pipe(res) + ); + if (req.method === 'GET') proxyReq.end(); + else req.pipe(proxyReq); + } + }); + + afterEach(async function () { + for (const conn of connections) { + if (!conn.destroyed) conn.destroy(); + } + httpServer.close(); + httpsServer.close(); + await Promise.all([once(httpServer, 'close'), once(httpsServer, 'close')]); + }); + + it('can connect using an HTTP proxy', async function () { + const shell = TestShell.start({ + args: [await testServer.connectionString()], + env: { + ...process.env, + MONGODB_PROXY: `http://localhost:${ + (httpServer.address() as AddressInfo).port + }/`, + }, + }); + + await shell.waitForPrompt(); + expect(connections).to.have.lengthOf.greaterThan(1); + const myself = await shell.executeLineWithJSONResult( + 'db.adminCommand({ whatsmyuri: 1 })' + ); + expect(myself.ok).to.equal(1); + expect(myself.you).to.be.oneOf(allConnectionIds()); + }); + + it('can connect using an HTTP proxy with auth', async function () { + const shell = TestShell.start({ + args: [await testServer.connectionString()], + env: { + ...process.env, + MONGODB_PROXY: `http://foo:bar@localhost:${ + (httpServer.address() as AddressInfo).port + }/`, + }, + }); + + await shell.waitForPrompt(); + expect(connections).to.have.lengthOf.greaterThan(1); + const myself = await shell.executeLineWithJSONResult( + 'db.adminCommand({ whatsmyuri: 1 })' + ); + expect(myself.ok).to.equal(1); + expect(myself.you).to.be.oneOf(allConnectionIds()); + for (const req of connectRequests) + expect(req.headers['proxy-authorization']).to.equal('Basic Zm9vOmJhcg=='); + }); + + it('can connect using an HTTP proxy specified via ALL_PROXY', async function () { + const shell = TestShell.start({ + args: [await testServer.connectionString()], + env: { + ...process.env, + ALL_PROXY: `http://foo:bar@localhost:${ + (httpServer.address() as AddressInfo).port + }/`, + }, + }); + + await shell.waitForPrompt(); + expect(connections).to.have.lengthOf.greaterThan(1); + const myself = await shell.executeLineWithJSONResult( + 'db.adminCommand({ whatsmyuri: 1 })' + ); + expect(myself.ok).to.equal(1); + expect(myself.you).to.be.oneOf(allConnectionIds()); + for (const req of connectRequests) + expect(req.headers['proxy-authorization']).to.equal('Basic Zm9vOmJhcg=='); + }); + + it('can connect using an HTTPS proxy (explicit CA on command line)', async function () { + const shell = TestShell.start({ + args: [await testServer.connectionString(), '--tlsCAFile', CA_CERT], + env: { + ...process.env, + MONGODB_PROXY: `https://localhost:${ + (httpsServer.address() as AddressInfo).port + }/`, + }, + }); + + await shell.waitForPrompt(); + expect(connections).to.have.lengthOf.greaterThan(1); + const myself = await shell.executeLineWithJSONResult( + 'db.adminCommand({ whatsmyuri: 1 })' + ); + expect(myself.ok).to.equal(1); + expect(myself.you).to.be.oneOf(allConnectionIds()); + }); + + it('can connect using an HTTPS proxy (CA in connection string)', async function () { + const shell = TestShell.start({ + args: [await testServer.connectionString({ tlsCAFile: CA_CERT })], + env: { + ...process.env, + MONGODB_PROXY: `https://localhost:${ + (httpsServer.address() as AddressInfo).port + }/`, + }, + }); + + await shell.waitForPrompt(); + expect(connections).to.have.lengthOf.greaterThan(1); + const myself = await shell.executeLineWithJSONResult( + 'db.adminCommand({ whatsmyuri: 1 })' + ); + expect(myself.ok).to.equal(1); + expect(myself.you).to.be.oneOf(allConnectionIds()); + }); + + it('can connect using an HTTPS proxy (CA in system list)', async function () { + if (process.platform !== 'linux') return this.skip(); + await fs.mkdir(path.join(tmpdir.path, 'certs'), { recursive: true }); + await fs.copyFile( + CA_CERT, + path.join(tmpdir.path, 'certs', 'somefilename.crt') + ); + + const shell = TestShell.start({ + args: [await testServer.connectionString()], + env: { + ...process.env, + MONGODB_PROXY: `https://localhost:${ + (httpsServer.address() as AddressInfo).port + }/`, + SSL_CERT_DIR: path.join(tmpdir.path, 'certs'), + }, + }); + + await shell.waitForPrompt(); + expect(connections).to.have.lengthOf.greaterThan(1); + const myself = await shell.executeLineWithJSONResult( + 'db.adminCommand({ whatsmyuri: 1 })' + ); + expect(myself.ok).to.equal(1); + expect(myself.you).to.be.oneOf(allConnectionIds()); + }); + + it('fails to connect using HTTPS proxy (no CA)', async function () { + const shell = TestShell.start({ + args: [await testServer.connectionString({ connectTimeoutMS: '2000' })], + env: { + ...process.env, + MONGODB_PROXY: `https://localhost:${ + (httpsServer.address() as AddressInfo).port + }/`, + }, + }); + + const code = await shell.waitForExit(); + expect(code).to.equal(1); + }); + + context('to a TLS server', function () { + const tlsServer = startTestServer('e2e-proxy-tls', { + args: [ + '--tlsMode', + 'requireTLS', + '--tlsCertificateKeyFile', + SERVER_BUNDLE, + '--tlsAllowConnectionsWithoutCertificates', + '--tlsCAFile', + CA_CERT, + ], + }); + + it('can connect using an HTTP proxy', async function () { + const shell = TestShell.start({ + args: [ + await connectionStringWithLocalhost(tlsServer, { + tlsCAFile: CA_CERT, + tls: 'true', + }), + ], + env: { + ...process.env, + MONGODB_PROXY: `http://localhost:${ + (httpServer.address() as AddressInfo).port + }/`, + }, + }); + + await shell.waitForPrompt(); + expect(connections).to.have.lengthOf.greaterThan(1); + const myself = await shell.executeLineWithJSONResult( + 'db.adminCommand({ whatsmyuri: 1 })' + ); + expect(myself.ok).to.equal(1); + expect(myself.you).to.be.oneOf(allConnectionIds()); + }); + + it('can connect using an HTTPS proxy', async function () { + const shell = TestShell.start({ + args: [ + await connectionStringWithLocalhost(tlsServer, { + tlsCAFile: CA_CERT, + tls: 'true', + }), + ], + env: { + ...process.env, + MONGODB_PROXY: `https://localhost:${ + (httpsServer.address() as AddressInfo).port + }/`, + }, + }); + + await shell.waitForPrompt(); + expect(connections).to.have.lengthOf.greaterThan(1); + const myself = await shell.executeLineWithJSONResult( + 'db.adminCommand({ whatsmyuri: 1 })' + ); + expect(myself.ok).to.equal(1); + expect(myself.you).to.be.oneOf(allConnectionIds()); + }); + }); + + it('will exclude a proxy host specified in NO_PROXY', async function () { + const shell = TestShell.start({ + args: [await testServer.connectionString()], + env: { + ...process.env, + MONGODB_PROXY: `http://localhost:${ + (httpServer.address() as AddressInfo).port + }/`, + NO_PROXY: 'localhost,127.0.0.1,::1', + }, + }); + + await shell.waitForPrompt(); + expect(connections).to.have.lengthOf(0); + const myself = await shell.executeLineWithJSONResult( + 'db.adminCommand({ whatsmyuri: 1 })' + ); + expect(myself.ok).to.equal(1); + expect(myself.you).not.to.be.oneOf(allConnectionIds()); + }); + + context('with OIDC', function () { + let getTokenPayload: typeof oidcMockProviderConfig.getTokenPayload; + let oidcMockProviderConfig: OIDCMockProviderConfig; + let oidcMockProvider: OIDCMockProvider; + let oidcMockProviderHttps: OIDCMockProvider; + let oidcTestServer: MongoRunnerSetup; + let tokenFetches: number; + + const fetchBrowserFixture = `"${path.resolve( + __dirname, + 'fixtures', + 'curl.mjs' + )}"`; + + before(async function () { + if (skipOIDCTestsDueToPlatformOrServerVersion()) { + // OIDC is only supported on Linux in the 7.0+ enterprise server, + // and we can't skip based on the dynamically detected server version because + // the OIDC config is something that needs to be available at server startup time. + return this.skip(); + } + + this.timeout(120_000); + oidcMockProviderConfig = { + getTokenPayload(metadata) { + return getTokenPayload(metadata); + }, + }; + const httpsServerKeyCertBundle = await fs.readFile(SERVER_BUNDLE); + [oidcMockProvider, oidcMockProviderHttps] = await Promise.all([ + OIDCMockProvider.create(oidcMockProviderConfig), + OIDCMockProvider.create({ + ...oidcMockProviderConfig, + createHTTPServer(requestListener) { + return createHTTPSServer( + { + key: httpsServerKeyCertBundle, + cert: httpsServerKeyCertBundle, + }, + requestListener + ); + }, + }), + ]); + oidcTestServer = new MongoRunnerSetup('e2e-proxy-oidc', { + args: [ + '--setParameter', + `oidcIdentityProviders=${JSON.stringify([ + { + ...baseOidcServerConfig, + clientId: 'testServer2', + matchPattern: '^testuser$', + authNamePrefix: 'dev', + issuer: oidcMockProvider.issuer, + }, + { + ...baseOidcServerConfig, + clientId: 'testServer2', + matchPattern: '^httpsIdPtestuser$', + authNamePrefix: 'https', + issuer: oidcMockProviderHttps.issuer, + }, + ])}`, + ...commonOidcServerArgs, + ], + }); + await oidcTestServer.start(); + }); + after(async function () { + this.timeout(120_000); + await Promise.all([ + oidcTestServer?.stop(), + oidcMockProvider?.close(), + oidcMockProviderHttps?.close(), + ]); + }); + + beforeEach(function () { + tokenFetches = 0; + getTokenPayload = (metadata) => { + tokenFetches++; + return { + expires_in: 3600, + payload: { + // Define the user information stored inside the access tokens + groups: [`${metadata.client_id}-group`], + sub: 'testuser', + aud: 'resource-server-audience-value', + }, + }; + }; + }); + + it('can route all traffic through the proxy', async function () { + const shell = TestShell.start({ + args: [ + await oidcTestServer.connectionString({}, { username: 'testuser' }), + '--authenticationMechanism=MONGODB-OIDC', + '--oidcRedirectUri=http://localhost:0/', + `--browser=${fetchBrowserFixture}`, + ], + env: { + ...process.env, + ALL_PROXY: `http://localhost:${ + (httpServer.address() as AddressInfo).port + }/`, + }, + }); + + await shell.waitForPrompt(); + expect(connections).to.have.lengthOf.greaterThan(1); + const myself = await shell.executeLineWithJSONResult( + 'db.adminCommand({ whatsmyuri: 1 })' + ); + expect(myself.ok).to.equal(1); + expect(myself.you).to.be.oneOf(allConnectionIds()); + const auth = await shell.executeLineWithJSONResult( + 'db.adminCommand({connectionStatus: 1})' + ); + expect(auth.authInfo.authenticatedUsers).to.deep.include({ + user: 'dev/testuser', + db: '$external', + }); + + expect([...new Set(connectRequests.map((req) => req.url))]).to.deep.equal( + [`127.0.0.1:${await oidcTestServer.port()}`] + ); + expect([ + ...new Set(httpForwardRequests.map((req) => new URL(req.url!).host)), + ]).to.deep.equal([ + `localhost:${ + (oidcMockProvider.httpServer.address() as AddressInfo).port + }`, + ]); + expect(tokenFetches).to.be.greaterThanOrEqual(1); + }); + + it('can route only http traffic through the proxy', async function () { + const shell = TestShell.start({ + args: [ + await oidcTestServer.connectionString({}, { username: 'testuser' }), + '--authenticationMechanism=MONGODB-OIDC', + '--oidcRedirectUri=http://localhost:0/', + `--browser=${fetchBrowserFixture}`, + ], + env: { + ...process.env, + HTTP_PROXY: `http://localhost:${ + (httpServer.address() as AddressInfo).port + }/`, + }, + }); + + await shell.waitForPrompt(); + const auth = await shell.executeLineWithJSONResult( + 'db.adminCommand({connectionStatus: 1})' + ); + expect(auth.authInfo.authenticatedUsers).to.deep.include({ + user: 'dev/testuser', + db: '$external', + }); + + expect(connectRequests).to.have.lengthOf(0); + expect([ + ...new Set(httpForwardRequests.map((req) => new URL(req.url!).host)), + ]).to.deep.equal([ + `localhost:${ + (oidcMockProvider.httpServer.address() as AddressInfo).port + }`, + ]); + expect(tokenFetches).to.be.greaterThanOrEqual(1); + }); + + it('can use a pac script to selectively route traffic', async function () { + const otherListeners = httpServer.listeners('request'); + httpServer.removeAllListeners('request'); + httpServer.on( + 'request', + function (this: HTTPServer, req: IncomingMessage, res: ServerResponse) { + (async () => { + if (req.url === '/pac') { + res.end(`function FindProxyForURL(url, host) { + if (url.includes(':${await oidcTestServer.port()}')) + return 'HTTP localhost:${ + (httpServer.address() as AddressInfo).port + }'; + return 'HTTPS localhost:${ + (httpsServer.address() as AddressInfo).port + }'; + }`); + } else { + for (const listener of otherListeners) + listener.call(this, req, res); + } + })().catch(console.error); + } + ); + const shell = TestShell.start({ + args: [ + await oidcTestServer.connectionString({}, { username: 'testuser' }), + '--authenticationMechanism=MONGODB-OIDC', + '--oidcRedirectUri=http://localhost:0/', + `--browser=${fetchBrowserFixture}`, + `--tlsCAFile=${CA_CERT}`, + ], + env: { + ...process.env, + ALL_PROXY: `pac+http://localhost:${ + (httpServer.address() as AddressInfo).port + }/pac`, + }, + }); + + await shell.waitForPrompt(); + expect(connections).to.have.lengthOf.greaterThan(1); + const myself = await shell.executeLineWithJSONResult( + 'db.adminCommand({ whatsmyuri: 1 })' + ); + expect(myself.ok).to.equal(1); + expect(myself.you).to.be.oneOf(allConnectionIds()); + const auth = await shell.executeLineWithJSONResult( + 'db.adminCommand({connectionStatus: 1})' + ); + expect(auth.authInfo.authenticatedUsers).to.deep.include({ + user: 'dev/testuser', + db: '$external', + }); + + expect([...new Set(connectRequests.map((req) => req.url))]).to.deep.equal( + [`127.0.0.1:${await oidcTestServer.port()}`] + ); + expect([ + ...new Set(httpForwardRequests.map((req) => new URL(req.url!).host)), + ]).to.deep.equal([ + `localhost:${ + (oidcMockProvider.httpServer.address() as AddressInfo).port + }`, + ]); + expect(tokenFetches).to.be.greaterThanOrEqual(1); + }); + + it('can route all traffic through the proxy (https, incomplete without CA)', async function () { + const shell = TestShell.start({ + args: [ + await oidcTestServer.connectionString( + {}, + { username: 'httpsIdPtestuser' } + ), + '--authenticationMechanism=MONGODB-OIDC', + '--oidcRedirectUri=http://localhost:0/', + `--browser=${fetchBrowserFixture}`, + `--tlsCAFile=${CA_CERT}`, + ], + env: { + ...process.env, + ALL_PROXY: `http://localhost:${ + (httpServer.address() as AddressInfo).port + }/`, + MONGOSH_E2E_TEST_CURL_ALLOW_INVALID_TLS: '1', + }, + }); + + await shell.waitForExit(); + // We cannot make the mongod server accept the mock IdP's certificate, + // so the best we can verify here is that auth failed *on the server* + shell.assertContainsOutput(/MongoServerError: Authentication failed/); + + expect( + [...new Set(connectRequests.map((req) => req.url))].sort() + ).to.deep.equal([ + `127.0.0.1:${await oidcTestServer.port()}`, + `localhost:${ + (oidcMockProviderHttps.httpServer.address() as AddressInfo).port + }`, + ]); + expect(tokenFetches).to.be.greaterThanOrEqual(1); + }); + }); +}); diff --git a/packages/e2e-tests/test/e2e-snapshot.spec.ts b/packages/e2e-tests/test/e2e-snapshot.spec.ts index b1b4961c8..8ba76403b 100644 --- a/packages/e2e-tests/test/e2e-snapshot.spec.ts +++ b/packages/e2e-tests/test/e2e-snapshot.spec.ts @@ -134,11 +134,11 @@ describe('e2e startup banners', function () { verifyAllInCategoryMatch('repl-eval', /^node_modules\/pretty-repl\//); verifyAllInCategoryMatch( 'db-eval', - /^node_modules\/(kerberos|os-dns-native|resolve-mongodb-srv|macos-export-certificate-and-key|win-export-certificate-and-key)\// + /^node_modules\/(kerberos|os-dns-native|resolve-mongodb-srv)\// ); verifyAllInCategoryMatch( 'nodb-eval', - /^node_modules\/(kerberos|mongodb-client-encryption|glibc-version|@mongodb-js\/devtools-proxy-support|@mongodb-js\/socksv5|system-ca)\// + /^node_modules\/(kerberos|mongodb-client-encryption|glibc-version|@mongodb-js\/devtools-proxy-support|@mongodb-js\/socksv5|agent-base|(win|macos)-export-certificate-and-key)\// ); verifyAllThatMatchAreInCategory( 'not-loaded', diff --git a/packages/e2e-tests/test/e2e-tls.spec.ts b/packages/e2e-tests/test/e2e-tls.spec.ts index 770874b95..573fa85e0 100644 --- a/packages/e2e-tests/test/e2e-tls.spec.ts +++ b/packages/e2e-tests/test/e2e-tls.spec.ts @@ -1,32 +1,16 @@ import { assert, expect } from 'chai'; import { promises as fs } from 'fs'; import path from 'path'; -import type { MongodSetup } from '../../../testing/integration-testing-hooks'; import { startTestServer } from '../../../testing/integration-testing-hooks'; import { useTmpdir, setTemporaryHomeDirectory, readReplLogfile, getCertPath, + connectionStringWithLocalhost, } from './repl-helpers'; import { TestShell } from './test-shell'; -// TLS requires matching hostnames, so here we need to explicitly -// specify `localhost` + IPv4 instead of `127.0.0.1` -async function connectionStringWithLocalhost( - setup: MongodSetup, - searchParams: Record = {} -): Promise { - const cs = await setup.connectionStringUrl(); - cs.hosts = cs.hosts.map((host) => - host.replace(/^(127.0.0.1)(?=$|:)/, 'localhost') - ); - cs.searchParams.set('family', '4'); - for (const [key, value] of Object.entries(searchParams)) - cs.searchParams.set(key, value); - return cs.toString(); -} - const CA_CERT = getCertPath('ca.crt'); const NON_CA_CERT = getCertPath('non-ca.crt'); const CLIENT_CERT = getCertPath('client.bundle.pem'); @@ -255,6 +239,10 @@ describe('e2e TLS', function () { logContents.find((line) => line.id === 1_000_000_049).attr .asyncFallbackError ).to.equal(null); // Ensure that system CA loading happened asynchronously. + expect( + logContents.find((line) => line.id === 1_000_000_049).attr + .systemCertsError + ).to.equal(null); // Ensure that system CA could be loaded successfully. }); it('works with system CA on Linux with SSL_CERT_FILE', async function () { @@ -288,6 +276,10 @@ describe('e2e TLS', function () { logContents.find((line) => line.id === 1_000_000_049).attr .asyncFallbackError ).to.equal(null); // Ensure that system CA loading happened asynchronously. + expect( + logContents.find((line) => line.id === 1_000_000_049).attr + .systemCertsError + ).to.equal(null); // Ensure that system CA could be loaded successfully. }); it('fails on macOS/Windows with system CA', async function () { diff --git a/packages/e2e-tests/test/oidc-helpers.ts b/packages/e2e-tests/test/oidc-helpers.ts new file mode 100644 index 000000000..9bb23ed31 --- /dev/null +++ b/packages/e2e-tests/test/oidc-helpers.ts @@ -0,0 +1,20 @@ +export const skipOIDCTestsDueToPlatformOrServerVersion = () => + process.platform !== 'linux' || + !process.env.MONGOSH_SERVER_TEST_VERSION || + !process.env.MONGOSH_SERVER_TEST_VERSION.includes('-enterprise'); + +export const baseOidcServerConfig = { + clientId: 'testServer', + requestScopes: ['mongodbGroups'], + authorizationClaim: 'groups', + audience: 'resource-server-audience-value', + authNamePrefix: 'dev', +} as const; + +export const commonOidcServerArgs = [ + '--setParameter', + 'authenticationMechanisms=SCRAM-SHA-256,MONGODB-OIDC', + // enableTestCommands allows using http:// issuers such as http://localhost + '--setParameter', + 'enableTestCommands=true', +]; diff --git a/packages/e2e-tests/test/repl-helpers.ts b/packages/e2e-tests/test/repl-helpers.ts index c3cd4de40..fbcd274c0 100644 --- a/packages/e2e-tests/test/repl-helpers.ts +++ b/packages/e2e-tests/test/repl-helpers.ts @@ -5,6 +5,7 @@ import rimraf from 'rimraf'; import chai from 'chai'; import sinonChai from 'sinon-chai'; import chaiAsPromised from 'chai-as-promised'; +import type { MongodSetup } from '../../../testing/integration-testing-hooks'; chai.use(sinonChai); chai.use(chaiAsPromised); @@ -141,6 +142,22 @@ function getCertPath(filename: string): string { ); } +// TLS requires matching hostnames, so here we need to explicitly +// specify `localhost` + IPv4 instead of `127.0.0.1` +async function connectionStringWithLocalhost( + setup: MongodSetup, + searchParams: Record = {} +): Promise { + const cs = await setup.connectionStringUrl(); + cs.hosts = cs.hosts.map((host) => + host.replace(/^(127.0.0.1)(?=$|:)/, 'localhost') + ); + cs.searchParams.set('family', '4'); + for (const [key, value] of Object.entries(searchParams)) + cs.searchParams.set(key, value); + return cs.toString(); +} + // eslint-disable-next-line mocha/no-exports export { useTmpdir, @@ -148,4 +165,5 @@ export { fakeExternalEditor, setTemporaryHomeDirectory, getCertPath, + connectionStringWithLocalhost, }; diff --git a/packages/e2e-tests/test/test-shell.ts b/packages/e2e-tests/test/test-shell.ts index 70ebd8f90..4474b07a7 100644 --- a/packages/e2e-tests/test/test-shell.ts +++ b/packages/e2e-tests/test/test-shell.ts @@ -9,6 +9,7 @@ import { once } from 'events'; import { inspect } from 'util'; import path from 'path'; import stripAnsi from 'strip-ansi'; +import { EJSON } from 'bson'; import { eventually } from '../../../testing/eventually'; export type TestShellStartupResult = @@ -240,6 +241,16 @@ export class TestShell { return this._output.slice(previousOutputLength); } + async executeLineWithJSONResult(line: string): Promise { + const output = await this.executeLine( + `">>>>>>" + EJSON.stringify(${line}, {relaxed:false}) + "<<<<<<"` + ); + const matching = output.match(/>>>>>>(.+)<<<<<=14.15.1" }, "dependencies": { - "@mongodb-js/devtools-connect": "^3.2.2", + "@mongodb-js/devtools-connect": "^3.2.4", "@mongosh/errors": "0.0.0-dev.0", "@mongosh/history": "0.0.0-dev.0", "@mongosh/types": "0.0.0-dev.0", diff --git a/packages/service-provider-server/package.json b/packages/service-provider-server/package.json index a2c536955..269599621 100644 --- a/packages/service-provider-server/package.json +++ b/packages/service-provider-server/package.json @@ -47,7 +47,7 @@ } }, "dependencies": { - "@mongodb-js/devtools-connect": "^3.2.2", + "@mongodb-js/devtools-connect": "^3.2.4", "@mongodb-js/oidc-plugin": "^1.1.1", "@mongosh/errors": "0.0.0-dev.0", "@mongosh/service-provider-core": "0.0.0-dev.0", diff --git a/packages/types/package.json b/packages/types/package.json index c29d11b4d..66f248d54 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -38,7 +38,7 @@ "unitTestsOnly": true }, "dependencies": { - "@mongodb-js/devtools-connect": "^3.2.2" + "@mongodb-js/devtools-connect": "^3.2.4" }, "devDependencies": { "@mongodb-js/eslint-config-mongosh": "^1.0.0",