From 9408385ba802b8862f200190e71abef5ba56709d Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Mon, 23 Sep 2019 21:20:43 -0400 Subject: [PATCH 1/3] Add optional ws router patcher due to possibility router.ws is missing Signed-off-by: 1000TurquoisePogs --- lib/webapp.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/webapp.js b/lib/webapp.js index 6c02ca81..cd38ed68 100644 --- a/lib/webapp.js +++ b/lib/webapp.js @@ -12,10 +12,12 @@ 'use strict'; const express = require('express'); +const expressApp = express(); +const expressWs = require('express-ws')(expressApp); + const fs = require('fs'); const util = require('util'); const url = require('url'); -const expressWs = require('express-ws'); const path = require('path'); const Promise = require('bluebird'); const http = require('http'); @@ -70,6 +72,7 @@ function DataserviceContext(serviceDefinition, serviceConfiguration, this.serviceConfiguration = serviceConfiguration; this.plugin = pluginContext; this.logger = createDataserviceLogger(pluginContext, serviceDefinition); + this.wsRouterPatcher = expressWs.applyTo; } function createDataserviceLogger(pluginContext, serviceDefinition) { @@ -939,7 +942,7 @@ function getAgentProxyOptions(serverConfig, agentConfig) { } function WebApp(options){ - this.expressApp = express(); + this.expressApp = expressApp; const port = options.httpsPort ? options.httpsPort : options.httpPort; this.expressApp.use(cookieParser()); this.expressApp.use(session({ @@ -962,7 +965,6 @@ function WebApp(options){ this.options = zluxUtil.makeOptionsObject(defaultOptions, options); this.auth = options.auth; this.configLocation = options.configLocation; - expressWs(this.expressApp); this.expressApp.serverInstanceUID = Date.now(); // hack this.pluginRouter = express.Router(); this.routers = {}; From 37d6ce955f826a9ee372339d322aca70d92a7aab Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Wed, 25 Sep 2019 08:42:50 -0400 Subject: [PATCH 2/3] update pl Signed-off-by: 1000TurquoisePogs --- package-lock.json | 89 +++++++++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 34 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5e53bf92..0a40abc3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "@types/body-parser": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", - "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.1.tgz", + "integrity": "sha512-RoX2EZjMiFMjZh9lmYrwgoP9RTpAjSHiJxdp4oidAQVO02T7HER3xj9UKue5534ULWeqVEkujhWcyvUce+d68w==", "dev": true, "requires": { "@types/connect": "*", @@ -15,9 +15,9 @@ } }, "@types/chai": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", - "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.3.tgz", + "integrity": "sha512-VRw2xEGbll3ZiTQ4J02/hUjNqZoue1bMhoo2dgM2LXjDdyaq4q80HgBDHwpI0/VKlo4Eg+BavyQMv/NYgTetzA==", "dev": true }, "@types/connect": { @@ -47,9 +47,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.7.tgz", - "integrity": "sha512-847KvL8Q1y3TtFLRTXcVakErLJQgdpFSaq+k043xefz9raEf0C7HalpSY7OW5PyjCnY8P7bPW5t/Co9qqp+USg==", + "version": "4.16.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.9.tgz", + "integrity": "sha512-GqpaVWR0DM8FnRUJYKlWgyARoBUAVfRIeVDZQKOttLFp5SmhhF9YFIYeTPwMd/AXfxlP7xVO2dj1fGu0Q+krKQ==", "dev": true, "requires": { "@types/node": "*", @@ -75,9 +75,9 @@ "dev": true }, "@types/serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz", + "integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==", "dev": true, "requires": { "@types/express-serve-static-core": "*", @@ -109,9 +109,9 @@ } }, "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", @@ -152,17 +152,17 @@ "dev": true }, "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "requires": { - "lodash": "^4.17.11" + "lodash": "^4.17.14" } }, "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, "asynckit": { "version": "0.4.0", @@ -475,6 +475,11 @@ "vary": "~1.1.2" }, "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", @@ -790,9 +795,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, "lodash.get": { "version": "4.4.2", @@ -971,9 +976,9 @@ } }, "psl": { - "version": "1.1.33", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.33.tgz", - "integrity": "sha512-LTDP2uSrsc7XCb5lO7A8BI1qYxRe/8EqlRvMeEl6rsnYAqDOl8xHR+8lSAIVfrNaSAlTPTNOCgNjWcoUL3AZsw==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", + "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==" }, "punycode": { "version": "2.1.1", @@ -1019,6 +1024,14 @@ "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } } }, "request": { @@ -1062,9 +1075,9 @@ } }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" }, "safer-buffer": { "version": "2.1.2", @@ -1152,6 +1165,14 @@ "dev": true, "requires": { "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } } }, "superagent": { @@ -1296,9 +1317,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" }, "validator": { "version": "10.11.0", From 9dac2d0d18705545020205739acaf73fac850a6b Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Thu, 3 Oct 2019 22:07:04 -0400 Subject: [PATCH 3/3] Allow auth plugins to modify headers being sent for cookie control Signed-off-by: 1000TurquoisePogs --- lib/index.js | 30 ++++++++++++++++-------------- lib/proxy.js | 15 +++++++++------ lib/webapp.js | 2 ++ lib/webauth.js | 25 +++++++++++++++++++++++-- 4 files changed, 50 insertions(+), 22 deletions(-) diff --git a/lib/index.js b/lib/index.js index 5f4b89b7..05bd2aa2 100755 --- a/lib/index.js +++ b/lib/index.js @@ -176,20 +176,12 @@ Server.prototype = { } util.deepFreeze(this.userConfig); this.webServer.setConfig(wsConfig); - const webauth = WebAuth(this.authManager); - /* - if either proxiedHost or proxiedPort were specified, then there is intent to connect to an agent. - However, zlux may be run without one, so if both are undefined then don't check for connection. - */ - if (process.platform !== 'os390' && - ((this.startUpConfig.proxiedHost !== undefined) || (this.startUpConfig.proxiedPort !== undefined))) { - const host = this.startUpConfig.proxiedHost; - const port = this.startUpConfig.proxiedPort; - yield checkProxiedHost(host, port); - } + const httpPort = wsConfig.http ? wsConfig.http.port : undefined; + const httpsPort = wsConfig.https ? wsConfig.https.port : undefined; + const cookiePort = httpsPort ? httpsPort : httpPort; const webAppOptions = { - httpPort: wsConfig.http ? wsConfig.http.port : undefined, - httpsPort: wsConfig.https ? wsConfig.https.port : undefined, + httpPort: httpPort, + httpsPort: httpsPort, productCode: this.appConfig.productCode, productDir: this.userConfig.productDir, proxiedHost: this.startUpConfig.proxiedHost, @@ -204,10 +196,20 @@ Server.prototype = { pluginMap: this.pluginLoader.pluginMap }, newPluginHandler: (pluginDef) => this.newPluginSubmitted(pluginDef), - auth: webauth, + auth: WebAuth(this.authManager, cookiePort, cookiePort === httpsPort), pluginLoader: this.pluginLoader, langManagers: this.langManagers }; + /* + if either proxiedHost or proxiedPort were specified, then there is intent to connect to an agent. + However, zlux may be run without one, so if both are undefined then don't check for connection. + */ + if (process.platform !== 'os390' && + ((this.startUpConfig.proxiedHost !== undefined) || (this.startUpConfig.proxiedPort !== undefined))) { + const host = this.startUpConfig.proxiedHost; + const port = this.startUpConfig.proxiedPort; + yield checkProxiedHost(host, port); + } this.webApp = makeWebApp(webAppOptions); this.webServer.startListening(this.webApp.expressApp); let pluginsLoaded = []; diff --git a/lib/proxy.js b/lib/proxy.js index 33a4510b..4d98cb05 100644 --- a/lib/proxy.js +++ b/lib/proxy.js @@ -61,7 +61,7 @@ function makeSimpleProxy(host, port, options, pluginID, serviceName) { + `For information on how to configure a proxy service, see the Zowe wiki on dataservices ` + `(https://github.com/zowe/zlux/wiki/ZLUX-Dataservices)`); } - const {urlPrefix, isHttps, addProxyAuthorizations, allowInvalidTLSProxy} = + const {urlPrefix, isHttps, addProxyAuthorizations, processProxiedHeaders, allowInvalidTLSProxy} = options; const httpApi = isHttps? https : http; return function(req1, res1) { @@ -81,20 +81,23 @@ function makeSimpleProxy(host, port, options, pluginID, serviceName) { const req2 = httpApi.request(requestOptions, (res2) => { proxyLog.debug("status code" + res2.statusCode); res1.status(res2.statusCode); - const headers = res2.headers; + const headers = processProxiedHeaders ? + processProxiedHeaders(req1, res2.headers) : + res2.headers; + for (const header of Object.keys(headers)) { if (header == 'location') { const location = headers[header]; let pattern = /^http.+\/ZLUX\/plugins\/.+/; if (!pattern.test(headers[header])) { if (location.startsWith('/')) { - res1.set(header, `${req1.protocol}://${req1.get('host')}/ZLUX/plugins/${pluginID}/services/${serviceName}/_current${location}`); + res1.set(header, `${req1.protocol}://${req1.get('host')}/ZLUX/plugins/${pluginID}/services/${serviceName}/_current${location}`); } else if (location.startsWith('http')) { - const locationParts = location.split(":"); + const locationParts = location.split(":"); let part; - if (locationParts.length > 2) { - part = locationParts[2]; + if (locationParts.length > 2) { + part = locationParts[2]; } else { part = locationParts[1] } diff --git a/lib/webapp.js b/lib/webapp.js index cd38ed68..2d775023 100644 --- a/lib/webapp.js +++ b/lib/webapp.js @@ -1009,6 +1009,7 @@ WebApp.prototype = { urlPrefix, isHttps: false, addProxyAuthorizations: (noAuth? null : this.auth.addProxyAuthorizations), + processProxiedHeaders: (noAuth? null: this.auth.processProxiedHeaders), allowInvalidTLSProxy: this.options.allowInvalidTLSProxy }; if (overrideOptions) { @@ -1029,6 +1030,7 @@ WebApp.prototype = { urlPrefix, isHttps, addProxyAuthorizations: (noAuth? null : this.auth.addProxyAuthorizations), + processProxiedHeaders: (noAuth? null : this.auth.processProxiedHeaders), allowInvalidTLSProxy: this.options.allowInvalidTLSProxy }, pluginID, serviceName); proxyMap.set(pluginID + ":" + serviceName, myProxy); diff --git a/lib/webauth.js b/lib/webauth.js index c88a1675..2b914b10 100644 --- a/lib/webauth.js +++ b/lib/webauth.js @@ -161,7 +161,7 @@ const SESSION_ACTION_TYPE_REFRESH = 2; /* * Assumes req.session is there and behaves as it should */ -module.exports = function(authManager) { +module.exports = function(authManager, cookiePort, isSecurePort) { const _authenticateOrRefresh = Promise.coroutine(function*(req, res, type) { let functionName; if (type == SESSION_ACTION_TYPE_AUTHENTICATE) { @@ -246,8 +246,26 @@ module.exports = function(authManager) { return; } const authPluginSession = getAuthPluginSession(req1, handler.pluginID, {}); - handler.addProxyAuthorizations(req1, req2Options, authPluginSession); + try { + handler.addProxyAuthorizations(req1, req2Options, authPluginSession); + } catch (e) { + authLogger.warn(`Failed to set proxy authorizations. Error=`,e); + } }, + + processProxiedHeaders(req, headers) { + const handler = getAuthHandler(req, authManager); + if (handler && handler.processProxiedHeaders) { + const authPluginSession = getAuthPluginSession(req, handler.pluginID, {}); + try { + return handler.processProxiedHeaders(req, headers, authPluginSession); + } catch (e) { + return headers; + } + } else { + return headers; + } + }, getStatus(req, res) { const handlers = authManager.getAllHandlers(); @@ -292,6 +310,9 @@ module.exports = function(authManager) { req.sessionStore.destroy(req.session.id); } req.session.id = null; + res.clearCookie('connect.sid.'+cookiePort, { path: '/', + httpOnly: true, + secure: isSecurePort}); } res.status(200).send(''); },