Skip to content

Commit

Permalink
Validate appfw plugins schema during component install (#3866)
Browse files Browse the repository at this point in the history
* Validate component appfw plugins during install time

Signed-off-by: 1000TurquoisePogs <sgrady@rocketsoftware.com>

* Cleanup on schema failure by not exiting in getPluginDefinition so that exit can be handled after cleanup

Signed-off-by: 1000TurquoisePogs <sgrady@rocketsoftware.com>

* Fix that manifest and plugindef were using same configmgr config id

Signed-off-by: 1000TurquoisePogs <sgrady@rocketsoftware.com>

---------

Signed-off-by: 1000TurquoisePogs <sgrady@rocketsoftware.com>
  • Loading branch information
1000TurquoisePogs authored Jun 25, 2024
1 parent a2a12b1 commit 26107c9
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ All notable changes to the Zowe Installer will be documented in this file.
## `2.17.0`

## New features and enhancements
- Enhancement: `zwe components install` and `zwe components upgrade` now checks the schema validity of any application framework plugins present within a component, so that you will know better if a component is valid prior to running Zowe. [#3866](https://github.com/zowe/zowe-install-packaging/pull/3866)
- Enhancement: Added zowe.network.server.tls.attls and zowe.network.client.tls.attls as booleans for controlling global or per-component way to tell Zowe servers that they should operate in a mode compatible with an AT-TLS setup. [#3463](https://github.com/zowe/zowe-install-packaging/pull/3463)

## `2.16.0`
Expand Down
14 changes: 14 additions & 0 deletions bin/commands/components/install/extract/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,20 @@ export function execute(componentFile: string, autoEncoding?: string, upgrade?:
common.printErrorAndExit(`Error ZWEL0167E: Cannot find component name from ${componentFile} package manifest`, undefined, 167);
}
common.printDebug(`- Component name found as ${componentName}`);

// If the component has appfw plugins, their validity should be checked against appfw plugin schema.
// If invalid, the installation will exit with an error message.
if (manifest.appfwPlugins) {
manifest.appfwPlugins.forEach((appfwPlugin: {path: string})=> {
let result = component.getPluginDefinition(pathoid.resolve(tmpDir, appfwPlugin.path), true);
//Normally, getPluginDefinition would quit upon failure. But we want to cleanup the tmpDir before that.
// So, we pass true to allow it to continue, check for null, and then remove the tmpdir and exit if so.
if (result === null) {
fs.rmrf(tmpDir);
std.exit(1);
}
});
}

const destinationDir = pathoid.resolve(targetDir, componentName);
const bkpDir = pathoid.resolve(targetDir, `${componentName}_zwebkp`);
Expand Down
33 changes: 19 additions & 14 deletions bin/libs/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,47 +114,52 @@ function showExceptions(e: any,depth: number): void {
}
}

export function getPluginDefinition(pluginRootPath:string) {
export function getPluginDefinition(pluginRootPath:string, continueOnFailure?: boolean) {
const pluginDefinitionPath = `${pluginRootPath}/pluginDefinition.json`;
const configId = `appfwPlugin:${pluginRootPath}`;

const printer = continueOnFailure ? common.printError : common.printErrorAndExit;

if (fs.fileExists(pluginDefinitionPath)) {
let status;
if ((status = CONFIG_MGR.addConfig(pluginRootPath))) {
common.printErrorAndExit(`Could not add config for ${pluginRootPath}, status=${status}`);
if ((status = CONFIG_MGR.addConfig(configId))) {
printer(`Could not add config for ${pluginRootPath}, status=${status}`);
return null;
}

if ((status = CONFIG_MGR.loadSchemas(pluginRootPath, PLUGIN_DEF_SCHEMAS))) {
common.printErrorAndExit(`Could not load schemas ${PLUGIN_DEF_SCHEMAS} for plugin ${pluginRootPath}, status=${status}`);
if ((status = CONFIG_MGR.loadSchemas(configId, PLUGIN_DEF_SCHEMAS))) {
printer(`Could not load schemas ${PLUGIN_DEF_SCHEMAS} for plugin ${pluginRootPath}, status=${status}`);
return null;
}


if ((status = CONFIG_MGR.setConfigPath(pluginRootPath, `FILE(${pluginDefinitionPath})`))) {
common.printErrorAndExit(`Could not set config path for ${pluginDefinitionPath}, status=${status}`);
if ((status = CONFIG_MGR.setConfigPath(configId, `FILE(${pluginDefinitionPath})`))) {
printer(`Could not set config path for ${pluginDefinitionPath}, status=${status}`);
return null;
}
if ((status = CONFIG_MGR.loadConfiguration(pluginRootPath))) {
common.printErrorAndExit(`Could not load config for ${pluginDefinitionPath}, status=${status}`);
if ((status = CONFIG_MGR.loadConfiguration(configId))) {
printer(`Could not load config for ${pluginDefinitionPath}, status=${status}`);
return null;
}

let validation = CONFIG_MGR.validate(pluginRootPath);
let validation = CONFIG_MGR.validate(configId);
if (validation.ok){
if (validation.exceptionTree){
common.printError(`Validation of ${pluginDefinitionPath} against schema ${PLUGIN_DEF_SCHEMA_ID} found invalid JSON Schema data`);
showExceptions(validation.exceptionTree, 0);
std.exit(1);
if (!continueOnFailure) {
std.exit(1);
}
return null;
} else {
return CONFIG_MGR.getConfigData(pluginRootPath);
return CONFIG_MGR.getConfigData(configId);
}
} else {
common.printErrorAndExit(`Error occurred on validation of ${pluginDefinitionPath} against schema ${PLUGIN_DEF_SCHEMA_ID} `);
printer(`Error occurred on validation of ${pluginDefinitionPath} against schema ${PLUGIN_DEF_SCHEMA_ID} `);
return null;
}
} else {
common.printErrorAndExit(`Plugin at ${pluginRootPath} has no pluginDefinition.json`);
printer(`Plugin at ${pluginRootPath} has no pluginDefinition.json`);
return null;
}
}
Expand Down

0 comments on commit 26107c9

Please sign in to comment.