UNPKG

@zowe/imperative

Version:
247 lines 15.2 kB
"use strict"; /* * 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 }); exports.ConfigAutoStore = void 0; const lodash = require("lodash"); const ConfigUtils_1 = require("./ConfigUtils"); const AbstractAuthHandler_1 = require("../../imperative/src/auth/handlers/AbstractAuthHandler"); const utilities_1 = require("../../utilities"); const Session_1 = require("../../rest/src/session/Session"); const SessConstants_1 = require("../../rest/src/session/SessConstants"); const logger_1 = require("../../logger"); /** * Class to manage automatic storage of properties in team config. */ class ConfigAutoStore { /** * Finds the profile where auto-store properties should be saved. * @param params CLI handler parameters object * @param profileProps List of properties required in the profile schema * @returns Tuple containing profile type and name, or undefined if no profile was found */ static findActiveProfile(params, profileProps) { return this._findActiveProfile({ params, profileProps }); } /** * Helper method to find an active profile based on the optional CLI handler parameters * @param opts Set of options required to find an active profile * @returns Tuple containing profile type and name, or undefined if no profile was found */ static _findActiveProfile(opts) { var _a, _b, _c, _d; const profileTypes = typeof opts.params !== "undefined" ? [ ...((_a = opts.params.definition.profile) === null || _a === void 0 ? void 0 : _a.required) || [], ...((_b = opts.params.definition.profile) === null || _b === void 0 ? void 0 : _b.optional) || [] ] : opts.profileTypes || []; for (const profType of profileTypes) { const profileMatch = (_c = utilities_1.ImperativeConfig.instance.loadedConfig.profiles) === null || _c === void 0 ? void 0 : _c.find(p => p.type === profType); if (profileMatch != null && opts.profileProps.every(propName => propName in profileMatch.schema.properties)) { return [profType, ConfigUtils_1.ConfigUtils.getActiveProfileName(profType, (_d = opts.params) === null || _d === void 0 ? void 0 : _d.arguments, opts.defaultProfileName)]; } } } /** * Finds the token auth handler class for a team config profile. * @param profilePath JSON path of profile * @param cmdArguments CLI arguments which may specify a profile * @returns Auth handler class or undefined if none was found */ static findAuthHandlerForProfile(profilePath, cmdArguments) { return this._findAuthHandlerForProfile({ profilePath, cmdArguments }); } /** * Helper method that finds the token auth handler class for a team config profile * @param opts Set of options required to find the auth handler for a given profile path * @returns Auth handler class or undefined if none was found */ static _findAuthHandlerForProfile(opts) { var _a; const config = opts.config || utilities_1.ImperativeConfig.instance.config; const profileType = lodash.get(config.properties, `${opts.profilePath}.type`); const profile = config.api.profiles.get(opts.profilePath.replace(/profiles\./g, ""), false); if (profile == null || profileType == null) { // Profile must exist and have type defined return; } else if (profileType === "base") { if (profile.tokenType == null) { // Base profile must have tokenType defined return; } } else { if (profile.basePath == null) { // Service profiles must have basePath defined return; } if (profile.tokenType == null) { // If tokenType undefined in service profile, fall back to base profile const baseProfileName = ConfigUtils_1.ConfigUtils.getActiveProfileName("base", opts.cmdArguments, opts.defaultBaseProfileName); return this._findAuthHandlerForProfile(Object.assign(Object.assign({}, opts), { profilePath: config.api.profiles.getProfilePathFromName(baseProfileName) })); } } const authConfigs = []; (_a = utilities_1.ImperativeConfig.instance.loadedConfig.profiles) === null || _a === void 0 ? void 0 : _a.forEach((profCfg) => { if ((profCfg.type === profileType || profCfg.type === "base") && profCfg.authConfig != null) { authConfigs.push(...profCfg.authConfig); } }); for (const authConfig of authConfigs) { const authHandler = require(authConfig.handler); const authHandlerClass = new authHandler.default(); if (authHandlerClass instanceof AbstractAuthHandler_1.AbstractAuthHandler) { const { promptParams } = authHandlerClass.getAuthHandlerApi(); if (profile.tokenType === promptParams.defaultTokenType || profile.tokenType.startsWith(SessConstants_1.TOKEN_TYPE_APIML)) { return authHandlerClass; // Auth service must have matching token type } } } } /** * Stores session config properties into a team config profile. * @param params CLI handler parameters object * @param sessCfg Session config containing properties to store * @param propsToStore Names of properties that should be stored */ static storeSessCfgProps(params, sessCfg, propsToStore) { return __awaiter(this, void 0, void 0, function* () { return this._storeSessCfgProps({ params, sessCfg, propsToStore }); }); } /** * Stores session config properties into a team config profile. * @param opts Set of options required to store session config properties */ static _storeSessCfgProps(opts) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e; const config = opts.config || utilities_1.ImperativeConfig.instance.config; // TODO Which autoStore value should take priority if it conflicts between layers if (opts.propsToStore.length == 0 || !(config === null || config === void 0 ? void 0 : config.exists) || !config.properties.autoStore) { logger_1.Logger.getAppLogger().info("Skipping update of profile properties. Check that config file exists and autoStore is true."); return; } let profileProps = opts.propsToStore.map(propName => propName === "hostname" ? "host" : propName); const profileData = this._findActiveProfile(Object.assign(Object.assign({}, opts), { profileProps })); if (profileData == null && opts.profileName == null && opts.profileType == null) { return; } const [profileType, profileName] = profileData !== null && profileData !== void 0 ? profileData : [opts.profileType, opts.profileName]; const profilePath = config.api.profiles.getProfilePathFromName(profileName); // Replace user and password with tokenValue if tokenType is defined in config if (profileProps.includes("user") && profileProps.includes("password") && (yield this._fetchTokenForSessCfg(Object.assign(Object.assign({}, opts), { profilePath })))) { profileProps = profileProps.filter(propName => propName !== "user" && propName !== "password"); profileProps.push("tokenValue"); } const beforeLayer = config.api.layers.get(); const profileObj = config.api.profiles.get(profileName, false); const profileSchema = (_b = (_a = utilities_1.ImperativeConfig.instance.loadedConfig.profiles) === null || _a === void 0 ? void 0 : _a.find(p => p.type === profileType)) === null || _b === void 0 ? void 0 : _b.schema; const profileSecureProps = config.api.secure.securePropsForProfile(profileName); const baseProfileName = ConfigUtils_1.ConfigUtils.getActiveProfileName("base", (_c = opts.params) === null || _c === void 0 ? void 0 : _c.arguments, opts.defaultBaseProfileName); const baseProfileObj = config.api.profiles.get(baseProfileName, false); const baseProfileSchema = utilities_1.ImperativeConfig.instance.loadedConfig.baseProfile.schema; const baseProfileSecureProps = config.api.secure.securePropsForProfile(baseProfileName); for (const propName of profileProps) { let propProfilePath = profilePath; let isSecureProp = ((_d = profileSchema === null || profileSchema === void 0 ? void 0 : profileSchema.properties[propName]) === null || _d === void 0 ? void 0 : _d.secure) || profileSecureProps.includes(propName); /* If any of the following is true, then property should be stored in base profile: (1) Service profile does not exist, but base profile does (2) Property is missing from service profile properties/secure objects, but present in base profile (3) Property is tokenValue and tokenType is missing from service profile, but present in base profile (4) Given profile is just a base profile :yum: */ if (!config.api.profiles.exists(profileName) && config.api.profiles.exists(baseProfileName) || profileObj[propName] == null && !profileSecureProps.includes(propName) && (baseProfileObj[propName] != null || baseProfileSecureProps.includes(propName)) || (propName === "tokenValue" && profileObj.tokenType == null && baseProfileObj.tokenType != null || profileType === "base")) { propProfilePath = config.api.profiles.getProfilePathFromName(baseProfileName); isSecureProp = baseProfileSchema.properties[propName].secure || baseProfileSecureProps.includes(propName); } // If secure array at higher level includes this property, then property should be stored at higher level if (isSecureProp) { const secureProfile = config.api.secure.secureInfoForProp(`${propProfilePath}.properties.${propName}`, true); let secureProfilePath; if (secureProfile != null) secureProfilePath = secureProfile.path; if (secureProfilePath != null && secureProfilePath.split(".").length < propProfilePath.split(".").length) { propProfilePath = secureProfilePath.slice(0, secureProfilePath.lastIndexOf(".")); } } const foundLayer = config.api.layers.find(config.api.profiles.getProfileNameFromPath(propProfilePath)); if (foundLayer != null) config.api.layers.activate(foundLayer.user, foundLayer.global); const sessCfgPropName = propName === "host" ? "hostname" : propName; config.set(`${propProfilePath}.properties.${propName}`, opts.sessCfg[sessCfgPropName], { secure: (_e = opts.setSecure) !== null && _e !== void 0 ? _e : isSecureProp }); } yield config.save(); const storedMsg = `Stored properties in ${config.layerActive().path}: ${profileProps.join(", ")}`; if (opts.params) { opts.params.response.console.log(storedMsg); } else { logger_1.Logger.getAppLogger().info(storedMsg); } // Restore original active layer config.api.layers.activate(beforeLayer.user, beforeLayer.global); }); } /** * Retrieves token value that will be auto-stored into session config. * @param params CLI handler parameters object * @param sessCfg Session config with credentials for basic or cert auth * @param profilePath JSON path of profile containing tokenType * @returns True if auth handler was found and token was fetched */ static fetchTokenForSessCfg(params, sessCfg, profilePath) { return __awaiter(this, void 0, void 0, function* () { return this._fetchTokenForSessCfg({ params, sessCfg, profilePath }); }); } /** * Helper function that retrieves token value that will be auto-stored into session config * @param opts Set of options required to fetch the token value to be auto-stored * @returns True if auth handler was found and token was fetched */ static _fetchTokenForSessCfg(opts) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c; const authHandlerClass = this._findAuthHandlerForProfile(opts); if (authHandlerClass == null) { return false; } const api = authHandlerClass.getAuthHandlerApi(); opts.sessCfg.type = SessConstants_1.AUTH_TYPE_TOKEN; opts.sessCfg.tokenType = (_c = (_b = (_a = opts.params) === null || _a === void 0 ? void 0 : _a.arguments) === null || _b === void 0 ? void 0 : _b.tokenType) !== null && _c !== void 0 ? _c : api.promptParams.defaultTokenType; const baseSessCfg = { type: opts.sessCfg.type }; for (const propName of Object.keys(utilities_1.ImperativeConfig.instance.loadedConfig.baseProfile.schema.properties)) { const sessCfgPropName = propName === "host" ? "hostname" : propName; if (opts.sessCfg[sessCfgPropName] != null) { baseSessCfg[sessCfgPropName] = opts.sessCfg[sessCfgPropName]; } } logger_1.Logger.getAppLogger().info(`Fetching ${opts.sessCfg.tokenType} for ${opts.profilePath}`); opts.sessCfg.tokenValue = yield api.sessionLogin(new Session_1.Session(baseSessCfg)); opts.sessCfg.user = opts.sessCfg.password = undefined; return true; }); } } exports.ConfigAutoStore = ConfigAutoStore; //# sourceMappingURL=ConfigAutoStore.js.map