@zowe/imperative
Version:
framework for building configurable CLIs
154 lines • 8.42 kB
JavaScript
;
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const config_1 = require("../../../../../config");
const ConfigAutoStore_1 = require("../../../../../config/src/ConfigAutoStore");
const ConfigUtils_1 = require("../../../../../config/src/ConfigUtils");
const error_1 = require("../../../../../error");
const logger_1 = require("../../../../../logger");
const rest_1 = require("../../../../../rest");
const utilities_1 = require("../../../../../utilities");
class SecureHandler {
/**
* Process the command and input.
*
* @param {IHandlerParameters} params Parameters supplied by yargs
*
* @throws {ImperativeError}
*/
process(params) {
return __awaiter(this, void 0, void 0, function* () {
this.params = params;
const config = utilities_1.ImperativeConfig.instance.config;
// Setup the credential vault API for the config
if (config.api.secure.loadFailed) {
throw ConfigUtils_1.ConfigUtils.secureSaveError();
}
if (params.arguments.prune) {
const prunedFiles = config.api.secure.rmUnusedProps();
if (prunedFiles.length > 0) {
yield config.api.secure.directSave();
params.response.console.log("Deleted secure properties for the following missing files:\n\t" +
prunedFiles.join("\n\t") +
"\n");
}
}
// Create the config, load the secure values, and activate the desired layer
config.api.layers.activate(params.arguments.userConfig, params.arguments.globalConfig);
let secureProps = config.api.secure.secureFields();
if (secureProps.length === 0) {
params.response.console.log("No secure properties found in your config");
return;
}
if (params.arguments.profile) {
const filteredSecureProps = secureProps.filter((prop) => config.api.profiles
.getProfileNameFromPath(prop)
.toLowerCase() ===
params.arguments.profile.toLowerCase());
if (filteredSecureProps.length === 0 && secureProps.length > 0) {
params.response.console.log(`No secure properties from profile '${params.arguments.profile}' found.`);
}
else {
secureProps = filteredSecureProps;
}
}
// Prompt for values designated as secure
for (const propName of secureProps) {
let propValue;
if (propName.endsWith(".tokenValue")) {
propValue = yield this.handlePromptForAuthToken(config, propName);
if (propValue === undefined) {
propValue = yield params.response.console.prompt(`Enter ${propName} ${config_1.ConfigConstants.SKIP_PROMPT}`, { hideText: true });
}
}
else {
propValue = yield params.response.console.prompt(`Enter ${propName} ${config_1.ConfigConstants.SKIP_PROMPT}`, { hideText: true });
// Save the value in the config securely
if (propValue) {
propValue = ConfigUtils_1.ConfigUtils.coercePropValue(propValue, config_1.ConfigSchema.findPropertyType(propName, config.properties));
}
}
// Save the value in the config securely
if (propValue) {
logger_1.Logger.getAppLogger().trace(`Setting property ${propName} to ${propValue}`);
config.set(propName, propValue, { secure: true });
}
}
// Write the config layer
yield config.save();
});
}
/**
* Checks if authentication service is associated with an auth token
* property. If an auth service is found, we log in to it obtain the token
* instead of prompting for the value.
* @param config Team config class from which the property was loaded
* @param propPath JSON property path of the auth token
* @returns Token value, or undefined if none was obtained
*/
handlePromptForAuthToken(config, propPath) {
return __awaiter(this, void 0, void 0, function* () {
const profilePath = propPath.slice(0, propPath.indexOf(".properties"));
const profile = config.api.profiles.get(profilePath.replace(/profiles\./g, ""), false);
const authHandlerClass = ConfigAutoStore_1.ConfigAutoStore.findAuthHandlerForProfile(profilePath, this.params.arguments);
if (authHandlerClass == null) {
// no auth handler service was associated with the specified profile
const tokenTypMsg = profile.tokenType ?
`of type '${profile.tokenType}'` : "with no associated tokenType";
this.params.response.console.log(utilities_1.TextUtils.wordWrap(utilities_1.TextUtils.chalk.yellowBright(`\nA profile requires a token ${tokenTypMsg} to be securely stored. ` +
`Supply a token at the prompt. Or press ENTER at the prompt and ` +
`later log in to your service for a token.\n`)));
// return undefined to allow prompting for tokenValue for this profile
return;
}
// call auth handler service that was associated with the specified profile
const api = authHandlerClass.getAuthHandlerApi();
if (api.promptParams.serviceDescription != null) {
this.params.response.console.log(utilities_1.TextUtils.wordWrap(utilities_1.TextUtils.chalk.yellowBright(`\nNow logging in to ${api.promptParams.serviceDescription} to get a token for profile ` +
`'${config.api.profiles.getProfileNameFromPath(propPath)}' ` +
`${config_1.ConfigConstants.SKIP_PROMPT}`)));
}
const sessCfg = api.createSessCfg(profile);
const sessCfgWithCreds = yield rest_1.ConnectionPropsForSessCfg.addPropsOrPrompt(sessCfg, profile, Object.assign({ parms: this.params, doPrompting: true, requestToken: true }, api.promptParams));
logger_1.Logger.getAppLogger().info(`Fetching ${profile.tokenType} for ${propPath}`);
if (rest_1.ConnectionPropsForSessCfg.sessHasCreds(sessCfgWithCreds)) {
try {
const tokenValue = yield api.sessionLogin(new rest_1.Session(sessCfgWithCreds));
this.params.response.console.log("Logged in successfully\n");
return tokenValue;
}
catch (error) {
throw new error_1.ImperativeError({
msg: `Failed to fetch ${profile.tokenType} for ${propPath}: ${error.message}`,
causeErrors: error,
});
}
}
else {
this.params.response.console.log("No credentials provided.\n");
// return null to avoid prompting for tokenValue for this profile
return null;
}
});
}
}
exports.default = SecureHandler;
//# sourceMappingURL=secure.handler.js.map