diff --git a/CHANGELOG.md b/CHANGELOG.md index aea3b8c2..e712e3a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to the Zlux Server Framework package will be documented in this file.. This repo is part of the app-server Zowe Component, and the change logs here may appear on Zowe.org in that section. +## 2.12.0 + +- Enhancement: Auth plugins that are not requested by any dataservice found at startup are no longer loaded by the server. + ## 2.11.0 - Enhancement: The title and description of the app server within the api catalog has been updated to be more complete, accurate, and useful. diff --git a/lib/assets/i18n/log/messages_en.json b/lib/assets/i18n/log/messages_en.json index 74c04fc8..46725905 100644 --- a/lib/assets/i18n/log/messages_en.json +++ b/lib/assets/i18n/log/messages_en.json @@ -187,6 +187,7 @@ "ZWED0300I": "APIML Storage configured", "ZWED0301I": "Found %s in config for '%s'", "ZWED0302I": "HA mode is %s", + "ZWED0303I": "Plugin %s will not be loaded because no dataservices requested it", "ZWED0003W":"User=%s (%s): Session %s failed. Plugin response: %s", "ZWED0004W":"Tomcat for ID=%s not starting, no services succeeded loading", diff --git a/lib/auth-manager.js b/lib/auth-manager.js index a96f0417..783ff90e 100644 --- a/lib/auth-manager.js +++ b/lib/auth-manager.js @@ -82,9 +82,32 @@ AuthManager.prototype = { registerAuthenticator(plugin) { this.pendingPlugins.push(plugin); }, + + getRequestedAuthCategories(startupPlugins, componentConfig) { + const requestedCategories = [componentConfig.dataserviceAuthentication.defaultAuthentication]; + startupPlugins.forEach((plugin)=> { + if (plugin.dataServices) { + plugin.dataServices.forEach((service)=> { + const authenticationData = + configService.getServiceConfiguration(plugin.identifier, plugin.location, + service.name, componentConfig, + componentConfig.node.productCode) + .getContents(['authentication.json']); + if (authenticationData && !requestedCategories.includes(authenticationData.authType)) { + requestedCategories.push(authenticationData.authType); + } + }); + } + }); + return requestedCategories; + }, - loadAuthenticators: Promise.coroutine(function*(config, tlsOptions) { + loadAuthenticators: Promise.coroutine(function*(config, tlsOptions, startupPlugins) { + const componentConfig = config.components['app-server']; + const requestedCategories = this.getRequestedAuthCategories(startupPlugins, componentConfig); + + let plugin; const isHaMode = zluxUtil.isHaMode(); while ((plugin = this.pendingPlugins.pop()) !== undefined) { @@ -92,7 +115,7 @@ AuthManager.prototype = { const authenticationHandler = yield plugin.authenticationModule( plugin, this.configuration, - config.components['app-server'], + componentConfig, new AuthPluginContext(plugin, tlsOptions)); // at this time we should have resolved plugin configuration to have a // nice list of info about what we are using to authenticate against @@ -107,7 +130,6 @@ AuthManager.prototype = { bootstrapLogger.warn('ZWED0178W', plugin.identifier); // "Skipping authentication plugin %s because it's not HA compatible" continue; } - this.handlers[plugin.identifier] = authenticationHandler; let categories; if (authenticationHandler.capabilities && authenticationHandler.capabilities.canGetCategories) { categories = authenticationHandler.getCategories(); @@ -116,6 +138,19 @@ AuthManager.prototype = { } else { categories = [plugin.authenticationCategory]; } + + //do not load this plugin if no dataservices are going to use it + let categoryFound = false; + for (let i = 0; i < categories.length; i++) { + if (requestedCategories.includes(categories[i])) { + categoryFound = true; + break; + } + } + if (!categoryFound) { + bootstrapLogger.info('ZWED0303I', plugin.identifier); + continue; //this plugin was not needed by any dataservice. including it may cause unnecessary auth requests to unnecessary endpoints. + } categories.forEach((category)=> { let pluginsByCategory = this.authTypes[category]; if (!pluginsByCategory) { @@ -136,6 +171,8 @@ AuthManager.prototype = { //`Authentication plugin ${plugin.identifier} added to category ` //+ `${category}`); }); + //load the plugin + this.handlers[plugin.identifier] = authenticationHandler; } catch (e) { authLog.warn('ZWED0008W', plugin.identifier, e); //authLog.warn(`error loading auth plugin ${plugin.identifier}: ` + e); } diff --git a/lib/index.js b/lib/index.js index 97fe593c..0a058589 100755 --- a/lib/index.js +++ b/lib/index.js @@ -267,9 +267,8 @@ Server.prototype = { this.configureApimlStorage(apimlConfig); } - yield this.loadPlugins(); - - yield this.authManager.loadAuthenticators(this.zoweConfig, Object.assign({},this.tlsOptions)); + const plugins = yield this.loadPlugins(); + yield this.authManager.loadAuthenticators(this.zoweConfig, Object.assign({},this.tlsOptions), plugins); this.authManager.validateAuthPluginList(); this.processManager.addCleanupFunction(function() { @@ -334,7 +333,7 @@ Server.prototype = { }); } }, installLogger)); - yield this.pluginLoader.loadPlugins(); + return yield this.pluginLoader.loadPlugins(); }), configureApimlStorage(apimlConfig) { diff --git a/lib/plugin-loader.js b/lib/plugin-loader.js index 94abcc30..78f9eb12 100644 --- a/lib/plugin-loader.js +++ b/lib/plugin-loader.js @@ -770,7 +770,7 @@ PluginLoader.prototype = { loadPlugins: Promise.coroutine(function*() { const defs = this.readPluginDefs(); - yield this.installPlugins(defs); + return yield this.installPlugins(defs); }), scanForPlugins() { @@ -867,12 +867,16 @@ PluginLoader.prototype = { } } this.registerStaticPluginsWithManagers(sortedAndRejectedPlugins.plugins); + + + for (const plugin of newPlugins) { this.emit('pluginFound', { data: plugin, count: newPlugins.length }); } + return yield Promise.resolve(newPlugins); }), // Note - Not to be confused with auth capabilities, that describe what an auth plugin can do diff --git a/lib/webapp.js b/lib/webapp.js index 6e7df64a..7097c397 100644 --- a/lib/webapp.js +++ b/lib/webapp.js @@ -1821,8 +1821,8 @@ WebApp.prototype = { case "router": { //installLog.info(`${plugin.identifier}: installing node router at ${subUrl}`); const serviceConfiguration = configService.getServiceConfiguration( - plugin.identifier, service.name, - pluginContext.server.config.app, this.options.componentConfig.node.productCode); + plugin.identifier, plugin.location, service.name, + this.options.componentConfig, this.options.componentConfig.node.productCode); const dataserviceContext = new DataserviceContext(service, serviceConfiguration, pluginContext, this); diff --git a/lib/webserver.js b/lib/webserver.js index 8216d1dd..0787af25 100644 --- a/lib/webserver.js +++ b/lib/webserver.js @@ -355,7 +355,7 @@ WebServer.prototype = { bootstrapLogger.debug('TLS trace:', this.httpsOptions.enableTrace ? 'enabled' : 'disabled'); readTlsOptionsFromConfig(nodeConfig, this.httpsOptions, zoweConfig.zowe?.certificate?.keystore?.password); } - }, + }, startListening: Promise.coroutine(function* (webapp) { if (this.config.https && this.config.https.port) {