Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip unused auth plugins #504

Merged
merged 10 commits into from
Oct 10, 2023
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions lib/assets/i18n/log/messages_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
43 changes: 40 additions & 3 deletions lib/auth-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,40 @@ 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) {
try {
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
Expand All @@ -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();
Expand All @@ -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) {
Expand All @@ -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);
}
Expand Down
7 changes: 3 additions & 4 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -334,7 +333,7 @@ Server.prototype = {
});
}
}, installLogger));
yield this.pluginLoader.loadPlugins();
return yield this.pluginLoader.loadPlugins();
}),

configureApimlStorage(apimlConfig) {
Expand Down
6 changes: 5 additions & 1 deletion lib/plugin-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ PluginLoader.prototype = {

loadPlugins: Promise.coroutine(function*() {
const defs = this.readPluginDefs();
yield this.installPlugins(defs);
return yield this.installPlugins(defs);
}),

scanForPlugins() {
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions lib/webapp.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion lib/webserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down