UNPKG

@axway/axway-central-cli

Version:

Manage APIs, services and publish to the Amplify Marketplace

509 lines (495 loc) 25.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.testables = exports.askBundleType = exports.AWSSaaSInstallMethods = void 0; var _chalk = _interopRequireDefault(require("chalk")); var _snooplogg = _interopRequireDefault(require("snooplogg")); var _basicPrompts = require("../../common/basicPrompts"); var _types = require("../../common/types"); var _utils = require("../../common/utils"); var _agents = require("./agents"); var helpers = _interopRequireWildcard(require("./helpers")); var _crypto = _interopRequireDefault(require("crypto")); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } const { log } = (0, _snooplogg.default)('engage: install: agents: saas'); const STAGE_TAG_NAME_LENGTH = 127; class DataplaneConfig { constructor(type) { _defineProperty(this, "type", void 0); this.type = type || ''; } } class AWSDataplaneConfig extends DataplaneConfig { constructor(arn, enableFullTransactionLogging, stageTagName) { super('AWS'); _defineProperty(this, "accessLogARN", void 0); _defineProperty(this, "fullTransactionLogging", void 0); _defineProperty(this, "stageTagName", void 0); this.accessLogARN = arn; this.fullTransactionLogging = enableFullTransactionLogging; this.stageTagName = stageTagName; } } class Sanitize { constructor(k, m) { _defineProperty(this, "keyMatch", void 0); _defineProperty(this, "valueMatch", void 0); this.keyMatch = k; this.valueMatch = m; } } class RedactionSet { constructor() { _defineProperty(this, "show", void 0); _defineProperty(this, "sanitize", void 0); this.show = []; this.sanitize = []; } } class Redaction { constructor() { _defineProperty(this, "maskingCharacter", void 0); _defineProperty(this, "path", void 0); _defineProperty(this, "queryArgument", void 0); _defineProperty(this, "requestHeaders", void 0); _defineProperty(this, "responseHeaders", void 0); this.maskingCharacter = '{*}'; this.path = []; this.queryArgument = new RedactionSet(); this.requestHeaders = new RedactionSet(); this.responseHeaders = new RedactionSet(); } } class SaasAgentValues { constructor() { _defineProperty(this, "frequencyDA", void 0); _defineProperty(this, "queueDA", void 0); _defineProperty(this, "filterDA", void 0); _defineProperty(this, "frequencyTA", void 0); _defineProperty(this, "redaction", void 0); _defineProperty(this, "dataplaneConfig", void 0); _defineProperty(this, "centralConfig", void 0); this.frequencyDA = ''; this.queueDA = false; this.frequencyTA = ''; this.filterDA = ''; this.redaction = new Redaction(); this.dataplaneConfig = new DataplaneConfig(); this.centralConfig = new _types.CentralAgentConfig(); } getAccessData() { return ''; } } class SaasAWSAgentValues extends SaasAgentValues { constructor() { super(); _defineProperty(this, "authType", void 0); _defineProperty(this, "accessKey", void 0); _defineProperty(this, "secretKey", void 0); _defineProperty(this, "region", void 0); _defineProperty(this, "assumeRole", void 0); _defineProperty(this, "externalID", void 0); _defineProperty(this, "accessLogARN", void 0); _defineProperty(this, "fullTransactionLogging", void 0); _defineProperty(this, "stageTagName", void 0); this.authType = AWSAuthType.ASSUME; this.accessKey = ''; this.secretKey = ''; this.region = ''; this.assumeRole = ''; this.externalID = ''; this.accessLogARN = ''; this.fullTransactionLogging = false; this.stageTagName = ''; } getAccessData() { let data = JSON.stringify({ region: this.region, roleARN: this.assumeRole, externalID: this.externalID }); if (this.authType == AWSAuthType.KEYS) { data = JSON.stringify({ region: this.region, accessKeyID: this.accessKey, secretAccessKey: this.secretKey }); } return data; } } // ConfigFiles - all the config file that are used in the setup const ConfigFiles = {}; // AWSAuthType - how the agent will authenticate to AWS var AWSAuthType = /*#__PURE__*/function (AWSAuthType) { AWSAuthType["ASSUME"] = "Assume Role Policy"; AWSAuthType["KEYS"] = "Access and Secret Keys"; return AWSAuthType; }(AWSAuthType || {}); // AWSSaaSPrompts - all AWS Saas prompts to the user for input const SaasPrompts = { AUTHENTICATION_TYPE: 'Authenticate with an AssumeRole Policy or an Access Key ID and Secret Access Key', ACCESS_KEY: 'Enter the AWS Access Key ID the agent will use', SECRET_KEY: 'Enter the AWS Secret Access Key the agent will use', ASSUME_ROLE: 'Enter the Role ARN that the agent will Assume', EXTERNAL_ID: 'Enter the External ID the Assume Role expects', ACCESS_LOG_ARN: 'Enter the ARN for the Access Log that the Discovery will add and the Traceability will use', STAGE_TAG_NAME: 'Enter the name of the tag on AWS API Gateway Stage that holds mapped stage on Amplify Engage', FULL_TRANSACTION_LOGGING: 'Do you want to enable Full Transaction Logging? Please note that CloudWatch costs would increase when Full Transaction Logging is enabled', DA_FREQUENCY: 'How often should the discovery run, leave blank for integrating in CI/CD process', DA_FILTER: 'Please enter the filter conditions for discovery of API Services based on tags', TA_FREQUENCY: 'How often should the traffic collection run, leave blank for manual trigger only', QUEUE: 'Do you want to discover immediately after installation', REDACT_SHOW: 'Enter a regular expression for {0}s that may be shown', ENTER_SANITIZE_RULE: 'Do you want to add sanitization rules for {0}s', SANITIZE_KEY: 'Enter a regular expression for {0} keys that values should be sanitized', SANITIZE_VAL: 'Enter a regular expression for sanitization of values when matching a {0} key', MASKING_CHARS: 'Enter the characters to use when sanitizing a value', ENTER_MORE: 'Do you want to enter another {0} for {1}' }; const askBundleType = async () => { return await (0, _basicPrompts.askList)({ msg: helpers.agentMessages.selectAgentType, choices: [_types.BundleType.ALL_AGENTS, _types.BundleType.DISCOVERY] }); }; exports.askBundleType = askBundleType; const askConfigType = async () => { return _types.AgentConfigTypes.HOSTED; }; // // Complex prompts // const askForRedactionSet = async (setting, redactionSet) => { // ask for path reg exs let askShow = true; console.log(_chalk.default.gray((0, _utils.FormatString)('\nRedaction settings for {0}s', setting))); while (askShow) { const input = await (0, _basicPrompts.askInput)({ msg: (0, _utils.FormatString)(SaasPrompts.REDACT_SHOW, setting), defaultValue: '.*', validate: (0, _basicPrompts.validateValidRegex)() }); redactionSet.show.push(input); askShow = (await (0, _basicPrompts.askList)({ msg: (0, _utils.FormatString)(SaasPrompts.ENTER_MORE, 'redaction regular expression', setting), default: _types.YesNo.No, choices: _types.YesNoChoices })) === _types.YesNo.Yes; } console.log(_chalk.default.gray((0, _utils.FormatString)('Sanitization settings for {0}s', setting))); let askSanitize = (await (0, _basicPrompts.askList)({ msg: (0, _utils.FormatString)(SaasPrompts.ENTER_SANITIZE_RULE, setting), default: _types.YesNo.No, choices: _types.YesNoChoices })) === _types.YesNo.Yes; console.log(_chalk.default.gray('When a match for the key regular expression is found, a match\nfor the value regular expression will be replaced by the masking character(s)')); while (askSanitize) { const keyMatch = await (0, _basicPrompts.askInput)({ msg: (0, _utils.FormatString)(SaasPrompts.SANITIZE_KEY, setting), allowEmptyInput: true, validate: (0, _basicPrompts.validateValidRegex)() }); const valMatch = await (0, _basicPrompts.askInput)({ msg: (0, _utils.FormatString)(SaasPrompts.SANITIZE_VAL, setting), allowEmptyInput: true, validate: (0, _basicPrompts.validateValidRegex)() }); if (keyMatch === '' || valMatch === '') { console.log("can't add sanitization rule with an empty key or value regular expression"); } else { redactionSet.sanitize.push(new Sanitize(keyMatch, valMatch)); } askSanitize = (await (0, _basicPrompts.askList)({ msg: (0, _utils.FormatString)(SaasPrompts.ENTER_MORE, 'sanitization rule', setting), default: _types.YesNo.No, choices: _types.YesNoChoices })) === _types.YesNo.Yes; } return redactionSet; }; const askForRedaction = async hostedAgentValues => { console.log(_chalk.default.gray('\nRedaction and Sanitization settings')); // ask for path reg exps let askPaths = true; console.log(_chalk.default.gray('\nRedaction settings for URL paths')); while (askPaths) { const input = await (0, _basicPrompts.askInput)({ msg: (0, _utils.FormatString)(SaasPrompts.REDACT_SHOW, 'URL path'), defaultValue: '.*', validate: (0, _basicPrompts.validateValidRegex)() }); hostedAgentValues.redaction.path.push(input); askPaths = (await (0, _basicPrompts.askList)({ msg: (0, _utils.FormatString)(SaasPrompts.ENTER_MORE, 'redaction regular expression', 'URL path'), default: _types.YesNo.No, choices: _types.YesNoChoices })) === _types.YesNo.Yes; } hostedAgentValues.redaction.queryArgument = await askForRedactionSet('query argument', hostedAgentValues.redaction.queryArgument); hostedAgentValues.redaction.requestHeaders = await askForRedactionSet('request header', hostedAgentValues.redaction.requestHeaders); hostedAgentValues.redaction.responseHeaders = await askForRedactionSet('response header', hostedAgentValues.redaction.responseHeaders); hostedAgentValues.redaction.maskingCharacter = await (0, _basicPrompts.askInput)({ msg: SaasPrompts.MASKING_CHARS, defaultValue: '{*}', validate: (0, _basicPrompts.validateRegex)(helpers.maskingRegex, 'Please enter a valid value') }); return hostedAgentValues; }; const askForAWSCredentials = async hostedAgentValues => { hostedAgentValues.region = await helpers.askAWSRegion(); log('gathering access details for aws'); // Ask Auth type hostedAgentValues.authType = await (0, _basicPrompts.askList)({ msg: SaasPrompts.AUTHENTICATION_TYPE, default: AWSAuthType.ASSUME, choices: [{ name: AWSAuthType.ASSUME, value: AWSAuthType.ASSUME }, { name: AWSAuthType.KEYS, value: AWSAuthType.KEYS }] }); console.log(_chalk.default.gray('Please refer to docs.axway.com for information on creating the necessary AWS IAM policies')); if (hostedAgentValues.authType === AWSAuthType.ASSUME) { log('using an assume role policy authentication'); // get assume role arn hostedAgentValues.assumeRole = await (0, _basicPrompts.askInput)({ msg: SaasPrompts.ASSUME_ROLE, defaultValue: hostedAgentValues.assumeRole !== '' ? hostedAgentValues.assumeRole : undefined, validate: (0, _basicPrompts.validateRegex)(helpers.AWSRegexPatterns.AWS_REGEXP_ROLE_ARN, helpers.invalidValueExampleErrMsg('assume role arn', 'arn:aws:iam::000000000000:role/name-of-role')) }); // get external id hostedAgentValues.externalID = await (0, _basicPrompts.askInput)({ msg: SaasPrompts.EXTERNAL_ID, defaultValue: hostedAgentValues.externalID !== '' ? hostedAgentValues.externalID : undefined, allowEmptyInput: true }); } else { log('using key and secret authentication'); // get access key hostedAgentValues.accessKey = await (0, _basicPrompts.askInput)({ msg: SaasPrompts.ACCESS_KEY, defaultValue: hostedAgentValues.accessKey !== '' ? hostedAgentValues.accessKey : undefined, validate: (0, _basicPrompts.validateRegex)(helpers.AWSRegexPatterns.AWS_REGEXP_ACCESS_KEY_ID, helpers.invalidValueExampleErrMsg('access key id', 'AKIAIOSFODNN7EXAMPLE')) }); // get secret access key hostedAgentValues.secretKey = await (0, _basicPrompts.askInput)({ msg: SaasPrompts.SECRET_KEY, defaultValue: hostedAgentValues.secretKey !== '' ? hostedAgentValues.secretKey : undefined, validate: (0, _basicPrompts.validateRegex)(helpers.AWSRegexPatterns.AWS_REGEXP_SECRET_ACCESS_KEY, helpers.invalidValueExampleErrMsg('secret access key', 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY')) }); } return hostedAgentValues; }; // @ts-ignore const gatewayConnectivity = async installConfig => { console.log('\nCONNECTION TO AMAZON API GATEWAY:'); console.log(_chalk.default.gray("The Discovery Agent needs to connect to the AWS API Gateway to discover API's for publishing to Amplify Engage")); // DeploymentType let hostedAgentValues = new SaasAgentValues(); if (installConfig.gatewayType === _types.GatewayTypes.AWS_GATEWAY) { // AWS connection details hostedAgentValues = new SaasAWSAgentValues(); hostedAgentValues = await askForAWSCredentials(hostedAgentValues); hostedAgentValues.stageTagName = await (0, _basicPrompts.askInput)({ msg: SaasPrompts.STAGE_TAG_NAME, validate: (0, _basicPrompts.validateInputLength)(STAGE_TAG_NAME_LENGTH, "Maximum length of 'stage tag name' is 127") }); if (installConfig.switches.isTaEnabled) { console.log(_chalk.default.gray('\nThe access log ARN is a cloud watch log group amazon resource name')); hostedAgentValues.accessLogARN = await (0, _basicPrompts.askInput)({ msg: SaasPrompts.ACCESS_LOG_ARN, validate: (0, _basicPrompts.validateRegex)(helpers.AWSRegexPatterns.AWS_ACCESS_LOG_ARN, helpers.invalidValueExampleErrMsg('access log arn', 'arn:aws:logs:region:000000000000:log-group:log-group-name')) }); hostedAgentValues.fullTransactionLogging = (await (0, _basicPrompts.askList)({ msg: SaasPrompts.FULL_TRANSACTION_LOGGING, default: _types.YesNo.No, choices: _types.YesNoChoices })) === _types.YesNo.Yes; } } // Ask to queue discovery now log('getting the frequency and if the agent should run now'); console.log(_chalk.default.gray('\n00d00h00m format, where 30m = 30 minutes, 1h = 1 hour, 7d = 7 days, and 7d1h30m = 7 days 1 hour and 30 minutes. Minimum of 30m.')); hostedAgentValues.frequencyDA = await (0, _basicPrompts.askInput)({ msg: SaasPrompts.DA_FREQUENCY, validate: (0, _agents.validateFrequency)(), allowEmptyInput: true }); hostedAgentValues.queueDA = (await (0, _basicPrompts.askList)({ msg: SaasPrompts.QUEUE, default: _types.YesNo.No, choices: _types.YesNoChoices })) === _types.YesNo.Yes; hostedAgentValues.filterDA = await (0, _basicPrompts.askInput)({ msg: SaasPrompts.DA_FILTER, allowEmptyInput: true }); if (installConfig.switches.isTaEnabled) { console.log(_chalk.default.gray('\n00d00h00m format, where 30m = 30 minutes, 1h = 1 hour, 7d = 7 days, and 7d1h30m = 7 days 1 hour and 30 minutes. Minimum of 30m.')); hostedAgentValues.frequencyTA = await (0, _basicPrompts.askInput)({ msg: SaasPrompts.TA_FREQUENCY, defaultValue: '30m', validate: (0, _agents.validateFrequency)(), allowEmptyInput: true }); hostedAgentValues = await askForRedaction(hostedAgentValues); } return hostedAgentValues; }; const generateOutput = async installConfig => { return `Install complete of hosted agent for ${installConfig.gatewayType} region`; }; const createEncryptedAccessData = async (hostedAgentValues, dataplaneRes) => { var _dataplaneRes$securit, _dataplaneRes$securit2; // grab key from data plane resource let key = ((_dataplaneRes$securit = dataplaneRes.security) === null || _dataplaneRes$securit === void 0 ? void 0 : _dataplaneRes$securit.encryptionKey) || ''; let hash = ((_dataplaneRes$securit2 = dataplaneRes.security) === null || _dataplaneRes$securit2 === void 0 ? void 0 : _dataplaneRes$securit2.encryptionHash) || ''; if (key === '' || hash === '') { throw Error(`cannot encrypt access data as the encryption key info was incomplete`); } let encData = _crypto.default.publicEncrypt({ key: key, padding: _crypto.default.constants.RSA_PKCS1_OAEP_PADDING, oaepHash: hash }, Buffer.from(hostedAgentValues.getAccessData())); return encData.toString('base64'); }; const completeInstall = async (installConfig, apiServerClient, defsManager) => { /** * Create agent resources */ console.log('\n'); let awsAgentValues = installConfig.gatewayConfig; let resourceFuncsForCleanup = []; let referencedIDPs = []; let providedIDPs = installConfig.idpConfig[0]; let providedIDPAuths = installConfig.idpConfig[1]; // create Identity Provider resource try { for (let i = 0; i < providedIDPs.length; i++) { let idpResource = await helpers.createNewIDPResource(apiServerClient, defsManager, providedIDPs[i]); let cleanupFunc = async () => await helpers.deleteByResourceType(apiServerClient, defsManager, idpResource === null || idpResource === void 0 ? void 0 : idpResource.name, 'IdentityProvider', 'idp'); resourceFuncsForCleanup.push(cleanupFunc); referencedIDPs.push({ name: idpResource === null || idpResource === void 0 ? void 0 : idpResource.name }); log(idpResource); let encryptedAccessData = await createEncryptedAccessData(providedIDPAuths[i], idpResource); providedIDPAuths[i].setAccessData(encryptedAccessData); let idpSecResource = await helpers.createNewIDPSecretResource(apiServerClient, defsManager, providedIDPAuths[i], idpResource); let anotherCleanupFunc = async () => await helpers.deleteByResourceType(apiServerClient, defsManager, idpSecResource === null || idpSecResource === void 0 ? void 0 : idpSecResource.name, 'IdentityProviderSecret', 'idpsec', idpResource === null || idpResource === void 0 ? void 0 : idpResource.name); resourceFuncsForCleanup.push(anotherCleanupFunc); } } catch (error) { log(error); console.log(_chalk.default.redBright('rolling back installation. Could not create the Identity Provider resources')); await cleanResources(resourceFuncsForCleanup); return; } let refIDPsSubResources = { references: { identityProviders: referencedIDPs } }; // create the environment, if necessary if (installConfig.centralConfig.ampcEnvInfo.isNew) { installConfig.centralConfig.environment = await helpers.createByResourceType(apiServerClient, defsManager, installConfig.centralConfig.ampcEnvInfo.name, 'Environment', 'env', { axwayManaged: installConfig.centralConfig.axwayManaged, production: installConfig.centralConfig.production }, '', refIDPsSubResources); let cleanupFunc = async () => await helpers.deleteByResourceType(apiServerClient, defsManager, installConfig.centralConfig.ampcEnvInfo.name, 'Environment', 'env'); resourceFuncsForCleanup.push(cleanupFunc); } else { // if the env exists, we simply update the references with the newly created IDPs, while preserving the existing IDP references // In the case of any failure during the whole process, we return everything back to how it was before. installConfig.centralConfig.environment = installConfig.centralConfig.ampcEnvInfo.name; refIDPsSubResources.references.identityProviders.push(...installConfig.centralConfig.ampcEnvInfo.referencedIdentityProviders); await helpers.updateSubResourceType(apiServerClient, defsManager, installConfig.centralConfig.ampcEnvInfo.name, 'Environment', 'env', '', refIDPsSubResources); let oldIDPRef = { references: { identityProviders: installConfig.centralConfig.ampcEnvInfo.referencedIdentityProviders } }; let cleanupFunc = async () => await helpers.updateSubResourceType(apiServerClient, defsManager, installConfig.centralConfig.ampcEnvInfo.name, 'Environment', 'env', '', oldIDPRef); resourceFuncsForCleanup.push(cleanupFunc); } if (installConfig.gatewayType === _types.GatewayTypes.AWS_GATEWAY) { if (installConfig.switches.isTaEnabled) { awsAgentValues.dataplaneConfig = new AWSDataplaneConfig(awsAgentValues.accessLogARN, awsAgentValues.fullTransactionLogging, awsAgentValues.stageTagName); } else { awsAgentValues.dataplaneConfig = new DataplaneConfig('AWS'); } } // create the data plane resource let dataplaneRes; try { dataplaneRes = await helpers.createNewDataPlaneResource(apiServerClient, defsManager, installConfig.centralConfig.environment, _types.GatewayTypeToDataPlane[installConfig.gatewayType], awsAgentValues.dataplaneConfig); let cleanupFunc = async () => await helpers.deleteByResourceType(apiServerClient, defsManager, dataplaneRes.name, 'Dataplane', 'dp', installConfig.centralConfig.environment); resourceFuncsForCleanup.push(cleanupFunc); } catch (error) { console.log(_chalk.default.redBright('rolling back installation. Please check the configuration data before re-running install')); await cleanResources(resourceFuncsForCleanup); return; } // create data plane secret resource try { let dataplaneSecretRes = await helpers.createNewDataPlaneSecretResource(apiServerClient, defsManager, installConfig.centralConfig.environment, _types.GatewayTypeToDataPlane[installConfig.gatewayType], dataplaneRes.name, await createEncryptedAccessData(awsAgentValues, dataplaneRes)); let cleanupFunc = async () => await helpers.deleteByResourceType(apiServerClient, defsManager, dataplaneSecretRes === null || dataplaneSecretRes === void 0 ? void 0 : dataplaneSecretRes.name, 'DataplaneSecret', 'dps', installConfig.centralConfig.environment); resourceFuncsForCleanup.push(cleanupFunc); } catch (error) { console.log(_chalk.default.redBright('rolling back installation. Please check the credential data before re-running install')); await cleanResources(resourceFuncsForCleanup); return; } // create discovery agent resource installConfig.centralConfig.daAgentName = await helpers.createNewAgentResource(apiServerClient, defsManager, installConfig.centralConfig.environment, _types.GatewayTypeToDataPlane[installConfig.gatewayType], _types.AgentResourceKind.da, _types.AgentTypes.da, installConfig.centralConfig.ampcTeamName, _types.GatewayTypeToDataPlane[installConfig.gatewayType] + ' Discovery Agent', dataplaneRes.name, awsAgentValues.frequencyDA, awsAgentValues.queueDA, undefined, awsAgentValues.filterDA); if (installConfig.switches.isTaEnabled) { // create traceability agent resource installConfig.centralConfig.taAgentName = await helpers.createNewAgentResource(apiServerClient, defsManager, installConfig.centralConfig.environment, _types.GatewayTypeToDataPlane[installConfig.gatewayType], _types.AgentResourceKind.ta, _types.AgentTypes.ta, installConfig.centralConfig.ampcTeamName, _types.GatewayTypeToDataPlane[installConfig.gatewayType] + ' Traceability Agent', dataplaneRes.name, awsAgentValues.frequencyTA, false, // AWS TA is never triggered at install, as DA has to run prior { redaction: awsAgentValues.redaction }); } console.log(await generateOutput(installConfig)); }; const AWSSaaSInstallMethods = exports.AWSSaaSInstallMethods = { GetBundleType: askBundleType, GetDeploymentType: askConfigType, AskGatewayQuestions: gatewayConnectivity, AddIDP: true, FinalizeGatewayInstall: completeInstall, ConfigFiles: [], AgentNameMap: { [_types.AgentTypes.da]: _types.AgentNames.AWS_DA, [_types.AgentTypes.ta]: _types.AgentNames.AWS_TA }, GatewayDisplay: _types.GatewayTypes.AWS_GATEWAY }; // These are the items that are not exported, but need to be for testing const testables = exports.testables = { SaasAgentValues, SaasAWSAgentValues, AWSAuthType, SaasPrompts, ConfigFiles }; // These are useful because there are multiple resources created in a specific order and in case of failure, this goes through // everything that was created and deletes it one by one. It deletes the resources in opposite order because resources added // at the beginning might be referred by resources added afterwards const cleanResources = async cleanupFuncs => { for (let i = cleanupFuncs.length - 1; i >= 0; i--) { await cleanupFuncs[i](); } };