"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isTransform = exports.installTransforms = void 0; var _elasticsearch = require("@elastic/elasticsearch"); var _jsYaml = require("js-yaml"); var _mlIsPopulatedObject = require("@kbn/ml-is-populated-object"); var _lodash = require("lodash"); var _transform_api_keys = require("../../../api_keys/transform_api_keys"); var _constants = require("../../../../../common/constants"); var _install = require("../template/install"); var _field = require("../../fields/field"); var _template = require("../template/template"); var _meta = require("../meta"); var _install2 = require("../../packages/install"); var _archive = require("../../archive"); var _models = require("../../../../../common/types/models"); var _packages = require("../../packages"); var _retry = require("../retry"); var _remove = require("./remove"); var _common = require("./common"); var _transform_utils = require("./transform_utils"); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ const DEFAULT_TRANSFORM_TEMPLATES_PRIORITY = 250; var TRANSFORM_SPECS_TYPES; (function (TRANSFORM_SPECS_TYPES) { TRANSFORM_SPECS_TYPES["MANIFEST"] = "manifest"; TRANSFORM_SPECS_TYPES["FIELDS"] = "fields"; TRANSFORM_SPECS_TYPES["TRANSFORM"] = "transform"; })(TRANSFORM_SPECS_TYPES || (TRANSFORM_SPECS_TYPES = {})); const installLegacyTransformsAssets = async (installablePackage, installNameSuffix, transformPaths, esClient, savedObjectsClient, logger, esReferences = [], previousInstalledTransformEsAssets = []) => { await (0, _remove.deleteTransforms)(esClient, previousInstalledTransformEsAssets.map(asset => asset.id), // For legacy transforms, delete destination indices upon deleting transforms true); let installedTransforms = []; if (transformPaths.length > 0) { const transformRefs = transformPaths.reduce((acc, path) => { acc.push({ id: getLegacyTransformNameForInstallation(installablePackage, path, installNameSuffix), type: _models.ElasticsearchAssetType.transform }); return acc; }, []); // get and save transform refs before installing transforms esReferences = await (0, _install2.updateEsAssetReferences)(savedObjectsClient, installablePackage.name, esReferences, { assetsToAdd: transformRefs }); const transforms = transformPaths.map(path => { const content = JSON.parse((0, _common.getAsset)(path).toString('utf-8')); content._meta = (0, _meta.getESAssetMetadata)({ packageName: installablePackage.name }); return { installationName: getLegacyTransformNameForInstallation(installablePackage, path, installNameSuffix), content }; }); const installationPromises = transforms.map(async transform => { return handleTransformInstall({ esClient, logger, transform }); }); installedTransforms = await Promise.all(installationPromises).then(results => results.flat()); } if (previousInstalledTransformEsAssets.length > 0) { esReferences = await (0, _install2.updateEsAssetReferences)(savedObjectsClient, installablePackage.name, esReferences, { assetsToRemove: previousInstalledTransformEsAssets }); } return { installedTransforms, esReferences }; }; const processTransformAssetsPerModule = (installablePackage, installNameSuffix, transformPaths, previousInstalledTransformEsAssets = [], force, username) => { const transformsSpecifications = new Map(); const destinationIndexTemplates = []; const transforms = []; const aliasesRefs = []; const transformsToRemove = []; const transformsToRemoveWithDestIndex = []; const indicesToAddRefs = []; transformPaths.forEach(path => { const { transformModuleId, fileName } = getTransformFolderAndFileNames(installablePackage, path); // Since there can be multiple assets per transform definition // We want to create a unique list of assets/specifications for each transform if (transformsSpecifications.get(transformModuleId) === undefined) { transformsSpecifications.set(transformModuleId, new Map()); } const packageAssets = transformsSpecifications.get(transformModuleId); const content = (0, _jsYaml.safeLoad)((0, _common.getAsset)(path).toString('utf-8')); if (fileName === TRANSFORM_SPECS_TYPES.FIELDS) { const validFields = (0, _field.processFields)(content); const mappings = (0, _template.generateMappings)(validFields); const templateName = getTransformAssetNameForInstallation(installablePackage, transformModuleId, 'template'); const indexToModify = destinationIndexTemplates.findIndex(t => t.transformModuleId === transformModuleId && t.installationName === templateName); const template = { transformModuleId, _meta: (0, _meta.getESAssetMetadata)({ packageName: installablePackage.name }), installationName: getTransformAssetNameForInstallation(installablePackage, transformModuleId, 'template'), template: {} }; if (indexToModify === -1) { destinationIndexTemplates.push(template); } else { destinationIndexTemplates[indexToModify] = template; } packageAssets === null || packageAssets === void 0 ? void 0 : packageAssets.set('mappings', mappings); } if (fileName === TRANSFORM_SPECS_TYPES.TRANSFORM) { var _content$_meta, _content$_meta2, _content$_meta3, _content$_meta$fleet_, _content$_meta4, _transformsSpecificat, _content$_meta5, _transformsSpecificat2, _transformsSpecificat3, _transformsSpecificat4, _transformsSpecificat5, _content$_meta6; const installationOrder = isFinite((_content$_meta = content._meta) === null || _content$_meta === void 0 ? void 0 : _content$_meta.order) && ((_content$_meta2 = content._meta) === null || _content$_meta2 === void 0 ? void 0 : _content$_meta2.order) >= 0 ? (_content$_meta3 = content._meta) === null || _content$_meta3 === void 0 ? void 0 : _content$_meta3.order : 0; const transformVersion = (_content$_meta$fleet_ = (_content$_meta4 = content._meta) === null || _content$_meta4 === void 0 ? void 0 : _content$_meta4.fleet_transform_version) !== null && _content$_meta$fleet_ !== void 0 ? _content$_meta$fleet_ : '0.1.0'; (_transformsSpecificat = transformsSpecifications.get(transformModuleId)) === null || _transformsSpecificat === void 0 ? void 0 : _transformsSpecificat.set('originalDestinationIndexName', content.dest.index); // Create two aliases associated with the destination index // for better handling during upgrades const aliases = (0, _transform_utils.getDestinationIndexAliases)(content.dest.aliases); const aliasNames = aliases.map(a => a.alias); // Override yml settings with alia format for transform's dest.aliases content.dest.aliases = aliases; indicesToAddRefs.push({ id: content.dest.index, type: _models.ElasticsearchAssetType.index }); // If run_as_kibana_system is not set, or is set to true, then run as kibana_system user // else, run with user's secondary credentials const runAsKibanaSystem = ((_content$_meta5 = content._meta) === null || _content$_meta5 === void 0 ? void 0 : _content$_meta5.run_as_kibana_system) !== false; (_transformsSpecificat2 = transformsSpecifications.get(transformModuleId)) === null || _transformsSpecificat2 === void 0 ? void 0 : _transformsSpecificat2.set('destinationIndex', content.dest); (_transformsSpecificat3 = transformsSpecifications.get(transformModuleId)) === null || _transformsSpecificat3 === void 0 ? void 0 : _transformsSpecificat3.set('destinationIndexAlias', aliases); (_transformsSpecificat4 = transformsSpecifications.get(transformModuleId)) === null || _transformsSpecificat4 === void 0 ? void 0 : _transformsSpecificat4.set('transform', content); (_transformsSpecificat5 = transformsSpecifications.get(transformModuleId)) === null || _transformsSpecificat5 === void 0 ? void 0 : _transformsSpecificat5.set('transformVersion', transformVersion); content._meta = { ...((_content$_meta6 = content._meta) !== null && _content$_meta6 !== void 0 ? _content$_meta6 : {}), ...(0, _meta.getESAssetMetadata)({ packageName: installablePackage.name }), ...(username ? { installed_by: username } : {}), run_as_kibana_system: runAsKibanaSystem }; const installationName = getTransformAssetNameForInstallation(installablePackage, transformModuleId, // transform_id is versioned by fleet_transform_version and not by package version `default-${transformVersion}`); // Here, we track if fleet_transform_version (not package version) has changed based on installation name // if version has changed, install transform and update es assets // else, don't delete the dest index and install transform as it can be an expensive operation const matchingTransformFromPrevInstall = previousInstalledTransformEsAssets.find(t => t.id === installationName); const currentTransformSameAsPrev = matchingTransformFromPrevInstall !== undefined; if (previousInstalledTransformEsAssets.length === 0) { var _transformsSpecificat6; aliasesRefs.push(...aliasNames); transforms.push({ transformModuleId, installationName, installationOrder, transformVersion, content, runAsKibanaSystem }); (_transformsSpecificat6 = transformsSpecifications.get(transformModuleId)) === null || _transformsSpecificat6 === void 0 ? void 0 : _transformsSpecificat6.set('transformVersionChanged', true); } else { if (force || !currentTransformSameAsPrev) { var _transformsSpecificat7; // If we are reinstalling the package (i.e. force = true), // force delete old transforms so we can reinstall the same transforms again if (force && matchingTransformFromPrevInstall) { transformsToRemoveWithDestIndex.push(matchingTransformFromPrevInstall); } else { // If upgrading from old json schema to new yml schema // We need to make sure to delete those transforms by matching the legacy naming convention const versionFromOldJsonSchema = previousInstalledTransformEsAssets.find(t => t.id.startsWith(getLegacyTransformNameForInstallation(installablePackage, `${transformModuleId}/default.json`))); if (versionFromOldJsonSchema !== undefined) { transformsToRemoveWithDestIndex.push(versionFromOldJsonSchema); } // If upgrading from yml to newer version of yaml // Match using new naming convention const installNameWithoutVersion = installationName.split(transformVersion)[0]; const prevVersion = previousInstalledTransformEsAssets.find(t => t.id.startsWith(installNameWithoutVersion)); if (prevVersion !== undefined) { transformsToRemove.push(prevVersion); } } transforms.push({ transformModuleId, installationName, installationOrder, transformVersion, content, runAsKibanaSystem }); (_transformsSpecificat7 = transformsSpecifications.get(transformModuleId)) === null || _transformsSpecificat7 === void 0 ? void 0 : _transformsSpecificat7.set('transformVersionChanged', true); if (aliasNames.length > 0) { aliasesRefs.push(...aliasNames); } } else { var _transformsSpecificat8; (_transformsSpecificat8 = transformsSpecifications.get(transformModuleId)) === null || _transformsSpecificat8 === void 0 ? void 0 : _transformsSpecificat8.set('transformVersionChanged', false); } } } // Create index templates for destination indices if destination_index_template OR fields are defined if (fileName === TRANSFORM_SPECS_TYPES.MANIFEST) { if ((0, _mlIsPopulatedObject.isPopulatedObject)(content, ['start']) && content.start === false) { var _transformsSpecificat9; (_transformsSpecificat9 = transformsSpecifications.get(transformModuleId)) === null || _transformsSpecificat9 === void 0 ? void 0 : _transformsSpecificat9.set('start', false); } if (content.destination_index_template) { const templateName = getTransformAssetNameForInstallation(installablePackage, transformModuleId, 'template'); const indexToModify = destinationIndexTemplates.findIndex(t => t.transformModuleId === transformModuleId && t.installationName === templateName); const template = { transformModuleId, _meta: (0, _meta.getESAssetMetadata)({ packageName: installablePackage.name }), installationName: getTransformAssetNameForInstallation(installablePackage, transformModuleId, 'template'), template: content.destination_index_template }; if (indexToModify === -1) { destinationIndexTemplates.push(template); } else { destinationIndexTemplates[indexToModify] = template; } packageAssets.set('destinationIndexTemplate', template); } } }); const indexTemplatesRefs = destinationIndexTemplates.map(template => { var _transformsSpecificat10; return { id: template.installationName, type: _models.ElasticsearchAssetType.indexTemplate, version: (_transformsSpecificat10 = transformsSpecifications.get(template.transformModuleId)) === null || _transformsSpecificat10 === void 0 ? void 0 : _transformsSpecificat10.get('transformVersion') }; }); const componentTemplatesRefs = [...destinationIndexTemplates.map(template => { var _transformsSpecificat11; return { id: `${template.installationName}${_constants.USER_SETTINGS_TEMPLATE_SUFFIX}`, type: _models.ElasticsearchAssetType.componentTemplate, version: (_transformsSpecificat11 = transformsSpecifications.get(template.transformModuleId)) === null || _transformsSpecificat11 === void 0 ? void 0 : _transformsSpecificat11.get('transformVersion') }; }), ...destinationIndexTemplates.map(template => { var _transformsSpecificat12; return { id: `${template.installationName}${_constants.PACKAGE_TEMPLATE_SUFFIX}`, type: _models.ElasticsearchAssetType.componentTemplate, version: (_transformsSpecificat12 = transformsSpecifications.get(template.transformModuleId)) === null || _transformsSpecificat12 === void 0 ? void 0 : _transformsSpecificat12.get('transformVersion') }; })]; const sortedTransforms = transforms.sort((t1, t2) => { var _t1$installationOrder, _t2$installationOrder; return ((_t1$installationOrder = t1.installationOrder) !== null && _t1$installationOrder !== void 0 ? _t1$installationOrder : 0) - ((_t2$installationOrder = t2.installationOrder) !== null && _t2$installationOrder !== void 0 ? _t2$installationOrder : 1); }); const transformRefs = sortedTransforms.map(t => ({ id: t.installationName, type: _models.ElasticsearchAssetType.transform, version: t.transformVersion })); return { indicesToAddRefs, indexTemplatesRefs, componentTemplatesRefs, transformRefs, transforms: sortedTransforms, destinationIndexTemplates, transformsSpecifications, aliasesRefs, transformsToRemove, transformsToRemoveWithDestIndex }; }; const installTransformsAssets = async (installablePackage, installNameSuffix, transformPaths, esClient, savedObjectsClient, logger, esReferences = [], previousInstalledTransformEsAssets = [], force, authorizationHeader) => { let installedTransforms = []; const username = authorizationHeader === null || authorizationHeader === void 0 ? void 0 : authorizationHeader.getUsername(); if (transformPaths.length > 0) { const { indicesToAddRefs, indexTemplatesRefs, componentTemplatesRefs, transformRefs, transforms, destinationIndexTemplates, transformsSpecifications, transformsToRemove, transformsToRemoveWithDestIndex } = processTransformAssetsPerModule(installablePackage, installNameSuffix, transformPaths, previousInstalledTransformEsAssets, force, username); // By default, for internal Elastic packages that touch system indices, we want to run as internal user // so we set runAsKibanaSystem: true by default (e.g. when run_as_kibana_system set to true/not defined in yml file). // If package should be installed as the logged in user, set run_as_kibana_system: false, // generate api key, and pass es-secondary-authorization in header when creating the transforms. const secondaryAuth = transforms.some(t => t.runAsKibanaSystem === false) ? await (0, _transform_api_keys.generateTransformSecondaryAuthHeaders)({ authorizationHeader, logger, pkgName: installablePackage.name, pkgVersion: installablePackage.version, username }) : // No need to generate api key/secondary auth if all transforms are run as kibana_system user undefined; // delete all previous transform await Promise.all([(0, _remove.deleteTransforms)(esClient, transformsToRemoveWithDestIndex.map(asset => asset.id), // Delete destination indices if specified or if from old json schema true, secondaryAuth), (0, _remove.deleteTransforms)(esClient, transformsToRemove.map(asset => asset.id), // Else, keep destination indices by default false, secondaryAuth)]); // get and save refs associated with the transforms before installing esReferences = await (0, _install2.updateEsAssetReferences)(savedObjectsClient, installablePackage.name, esReferences, { assetsToAdd: [...indicesToAddRefs, ...indexTemplatesRefs, ...componentTemplatesRefs, ...transformRefs], assetsToRemove: [...transformsToRemove, ...transformsToRemoveWithDestIndex] }); // create index templates and component templates await Promise.all(destinationIndexTemplates.map(destinationIndexTemplate => { var _transformSpec$get, _transformSpec$get2, _transformSpec$get3; const transformSpec = transformsSpecifications.get(destinationIndexTemplate.transformModuleId); const customMappings = (_transformSpec$get = transformSpec === null || transformSpec === void 0 ? void 0 : transformSpec.get('mappings')) !== null && _transformSpec$get !== void 0 ? _transformSpec$get : {}; const pipelineId = transformSpec === null || transformSpec === void 0 ? void 0 : (_transformSpec$get2 = transformSpec.get('destinationIndex')) === null || _transformSpec$get2 === void 0 ? void 0 : _transformSpec$get2.pipeline; const transformVersionChanged = (_transformSpec$get3 = transformSpec === null || transformSpec === void 0 ? void 0 : transformSpec.get('transformVersionChanged')) !== null && _transformSpec$get3 !== void 0 ? _transformSpec$get3 : true; if (!transformVersionChanged) return; const registryElasticsearch = { 'index_template.settings': destinationIndexTemplate.template.settings, 'index_template.mappings': destinationIndexTemplate.template.mappings }; const componentTemplates = (0, _install.buildComponentTemplates)({ mappings: customMappings, templateName: destinationIndexTemplate.installationName, registryElasticsearch, packageName: installablePackage.name, defaultSettings: { // Adding destination pipeline here because else these templates will be overridden // by index setting ...(pipelineId ? { default_pipeline: pipelineId } : {}) } }); if (destinationIndexTemplate || customMappings) { var _transformsSpecificat13; return (0, _install.installComponentAndIndexTemplateForDataStream)({ esClient, logger, componentTemplates, indexTemplate: { templateName: destinationIndexTemplate.installationName, // @ts-expect-error data_stream property is not needed here indexTemplate: { template: { settings: undefined, mappings: undefined }, priority: DEFAULT_TRANSFORM_TEMPLATES_PRIORITY, index_patterns: [(_transformsSpecificat13 = transformsSpecifications.get(destinationIndexTemplate.transformModuleId)) === null || _transformsSpecificat13 === void 0 ? void 0 : _transformsSpecificat13.get('destinationIndex').index], _meta: destinationIndexTemplate._meta, composed_of: Object.keys(componentTemplates) } } }); } }).filter(p => p !== undefined)); // If the transforms have specific installation order, install & optionally start transforms sequentially const shouldInstallSequentially = (0, _lodash.uniqBy)(transforms, 'installationOrder').length === transforms.length; if (shouldInstallSequentially) { for (const transform of transforms) { var _transformsSpecificat14; const installTransform = await handleTransformInstall({ esClient, logger, transform, startTransform: (_transformsSpecificat14 = transformsSpecifications.get(transform.transformModuleId)) === null || _transformsSpecificat14 === void 0 ? void 0 : _transformsSpecificat14.get('start'), secondaryAuth: transform.runAsKibanaSystem !== false ? undefined : secondaryAuth }); installedTransforms.push(installTransform); } } else { // Else, create & start all the transforms at once for speed const transformsPromises = transforms.map(async transform => { var _transformsSpecificat15; return handleTransformInstall({ esClient, logger, transform, startTransform: (_transformsSpecificat15 = transformsSpecifications.get(transform.transformModuleId)) === null || _transformsSpecificat15 === void 0 ? void 0 : _transformsSpecificat15.get('start'), secondaryAuth: transform.runAsKibanaSystem !== false ? undefined : secondaryAuth }); }); installedTransforms = await Promise.all(transformsPromises).then(results => results.flat()); } // If user does not have sufficient permissions to start the transforms, // we need to mark them as deferred installations without blocking full package installation // so that they can be updated/re-authorized later if (installedTransforms.length > 0) { // get and save refs associated with the transforms before installing esReferences = await (0, _install2.updateEsAssetReferences)(savedObjectsClient, installablePackage.name, esReferences, { assetsToRemove: installedTransforms, assetsToAdd: installedTransforms }); } } return { installedTransforms, esReferences }; }; const installTransforms = async ({ installablePackage, paths, esClient, savedObjectsClient, logger, force, esReferences, authorizationHeader }) => { var _ref, _esReferences; const transformPaths = paths.filter(path => isTransform(path)); const installation = await (0, _packages.getInstallation)({ savedObjectsClient, pkgName: installablePackage.name }); esReferences = (_ref = (_esReferences = esReferences) !== null && _esReferences !== void 0 ? _esReferences : installation === null || installation === void 0 ? void 0 : installation.installed_es) !== null && _ref !== void 0 ? _ref : []; let previousInstalledTransformEsAssets = []; if (installation) { previousInstalledTransformEsAssets = installation.installed_es.filter(({ type, id }) => type === _models.ElasticsearchAssetType.transform); if (previousInstalledTransformEsAssets.length > 0) { logger.debug(`Found previous transform references:\n ${JSON.stringify(previousInstalledTransformEsAssets)}`); } } const installNameSuffix = `${installablePackage.version}`; // If package contains legacy transform specifications (i.e. with json instead of yml) if (transformPaths.some(p => p.endsWith('.json')) || transformPaths.length === 0) { return await installLegacyTransformsAssets(installablePackage, installNameSuffix, transformPaths, esClient, savedObjectsClient, logger, esReferences, previousInstalledTransformEsAssets); } // If package contains yml transform specifications return await installTransformsAssets(installablePackage, installNameSuffix, transformPaths, esClient, savedObjectsClient, logger, esReferences, previousInstalledTransformEsAssets, force, authorizationHeader); }; exports.installTransforms = installTransforms; const isTransform = path => { const pathParts = (0, _archive.getPathParts)(path); return !path.endsWith('/') && pathParts.type === _models.ElasticsearchAssetType.transform; }; exports.isTransform = isTransform; /** * Create transform and optionally start transform * Note that we want to add the current user's roles/permissions to the es-secondary-auth with a API Key. * If API Key has insufficient permissions, it should still create the transforms but not start it * Instead of failing, we need to allow package to continue installing other assets * and prompt for users to authorize the transforms with the appropriate permissions after package is done installing */ async function handleTransformInstall({ esClient, logger, transform, startTransform, secondaryAuth }) { let isUnauthorizedAPIKey = false; try { await (0, _retry.retryTransientEsErrors)(() => // defer_validation: true on put if the source index is not available // but will check if API Key has sufficient permission esClient.transform.putTransform({ transform_id: transform.installationName, defer_validation: true, body: transform.content }, // add '{ headers: { es-secondary-authorization: 'ApiKey {encodedApiKey}' } }' secondaryAuth ? { ...secondaryAuth } : undefined), { logger }); logger.debug(`Created transform: ${transform.installationName}`); } catch (err) { var _err$body, _err$body$error, _err$body2, _err$body2$error, _err$body2$error$reas, _err$body3, _err$body3$error; const isResponseError = err instanceof _elasticsearch.errors.ResponseError; isUnauthorizedAPIKey = isResponseError && (err === null || err === void 0 ? void 0 : (_err$body = err.body) === null || _err$body === void 0 ? void 0 : (_err$body$error = _err$body.error) === null || _err$body$error === void 0 ? void 0 : _err$body$error.type) === 'security_exception' && (err === null || err === void 0 ? void 0 : (_err$body2 = err.body) === null || _err$body2 === void 0 ? void 0 : (_err$body2$error = _err$body2.error) === null || _err$body2$error === void 0 ? void 0 : (_err$body2$error$reas = _err$body2$error.reason) === null || _err$body2$error$reas === void 0 ? void 0 : _err$body2$error$reas.includes('unauthorized for API key')); const isAlreadyExistError = isResponseError && (err === null || err === void 0 ? void 0 : (_err$body3 = err.body) === null || _err$body3 === void 0 ? void 0 : (_err$body3$error = _err$body3.error) === null || _err$body3$error === void 0 ? void 0 : _err$body3$error.type) === 'resource_already_exists_exception'; // swallow the error if the transform already exists or if API key has insufficient permissions if (!isUnauthorizedAPIKey && !isAlreadyExistError) { throw err; } } // start transform by default if not set in yml file // else, respect the setting if (startTransform === undefined || startTransform === true) { try { await (0, _retry.retryTransientEsErrors)(() => esClient.transform.startTransform({ transform_id: transform.installationName }, { ignore: [409] }), { logger, additionalResponseStatuses: [400] }); logger.debug(`Started transform: ${transform.installationName}`); } catch (err) { var _err$body4, _err$body4$error, _err$body5, _err$body5$error, _err$body5$error$reas; const isResponseError = err instanceof _elasticsearch.errors.ResponseError; isUnauthorizedAPIKey = isResponseError && // if transform was created with insufficient permission, // _start will yield an error (err === null || err === void 0 ? void 0 : (_err$body4 = err.body) === null || _err$body4 === void 0 ? void 0 : (_err$body4$error = _err$body4.error) === null || _err$body4$error === void 0 ? void 0 : _err$body4$error.type) === 'security_exception' && (err === null || err === void 0 ? void 0 : (_err$body5 = err.body) === null || _err$body5 === void 0 ? void 0 : (_err$body5$error = _err$body5.error) === null || _err$body5$error === void 0 ? void 0 : (_err$body5$error$reas = _err$body5$error.reason) === null || _err$body5$error$reas === void 0 ? void 0 : _err$body5$error$reas.includes('lacks the required permissions')); // swallow the error if the transform can't be started if API key has insufficient permissions if (!isUnauthorizedAPIKey) { throw err; } } } else { // if transform was not set to start automatically in yml config, // we need to check using _stats if the transform had insufficient permissions try { const transformStats = await (0, _retry.retryTransientEsErrors)(() => esClient.transform.getTransformStats({ transform_id: transform.installationName }, { ignore: [409] }), { logger, additionalResponseStatuses: [400] }); if (Array.isArray(transformStats.transforms) && transformStats.transforms.length === 1) { const transformHealth = transformStats.transforms[0].health; if (transformHealth && transformHealth.status === 'red' && // @ts-expect-error TransformGetTransformStatsTransformStatsHealth should have 'issues' Array.isArray(transformHealth.issues) && // @ts-expect-error TransformGetTransformStatsTransformStatsHealth should have 'issues' transformHealth.issues.find(i => i.issue === 'Privileges check failed')) { isUnauthorizedAPIKey = true; } } } catch (err) { logger.debug(`Error getting transform stats for transform: ${transform.installationName} cause ${err}`); } } return { id: transform.installationName, type: _models.ElasticsearchAssetType.transform, // If isUnauthorizedAPIKey: true (due to insufficient user permission at transform creation) // that means the transform is created but not started. // Note in saved object this is a deferred installation so user can later reauthorize deferred: isUnauthorizedAPIKey, version: transform.transformVersion }; } const getLegacyTransformNameForInstallation = (installablePackage, path, suffix) => { var _pathPaths$pop; const pathPaths = path.split('/'); const filename = pathPaths === null || pathPaths === void 0 ? void 0 : (_pathPaths$pop = pathPaths.pop()) === null || _pathPaths$pop === void 0 ? void 0 : _pathPaths$pop.split('.')[0]; const folderName = pathPaths === null || pathPaths === void 0 ? void 0 : pathPaths.pop(); return `${installablePackage.name}.${folderName}-${filename}${suffix ? '-' + suffix : ''}`; }; const getTransformAssetNameForInstallation = (installablePackage, transformModuleId, suffix) => { return `logs-${installablePackage.name}.${transformModuleId}${suffix ? '-' + suffix : ''}`; }; const getTransformFolderAndFileNames = (installablePackage, path) => { var _pathPaths$pop2, _transformModuleId; const pathPaths = path.split('/'); const fileName = pathPaths === null || pathPaths === void 0 ? void 0 : (_pathPaths$pop2 = pathPaths.pop()) === null || _pathPaths$pop2 === void 0 ? void 0 : _pathPaths$pop2.split('.')[0]; let transformModuleId = pathPaths === null || pathPaths === void 0 ? void 0 : pathPaths.pop(); // If fields.yml is located inside a directory called 'fields' (e.g. {exampleFolder}/fields/fields.yml) // We need to go one level up to get the real folder name if (transformModuleId === 'fields') { transformModuleId = pathPaths === null || pathPaths === void 0 ? void 0 : pathPaths.pop(); } return { fileName: fileName !== null && fileName !== void 0 ? fileName : '', transformModuleId: (_transformModuleId = transformModuleId) !== null && _transformModuleId !== void 0 ? _transformModuleId : '' }; };