"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.generateFleetConfig = generateFleetConfig; exports.getFullAgentPolicy = getFullAgentPolicy; exports.transformOutputToFullPolicyOutput = transformOutputToFullPolicyOutput; var _jsYaml = require("js-yaml"); var _deepmerge = _interopRequireDefault(require("deepmerge")); var _agent_policy = require("../agent_policy"); var _constants = require("../../../common/constants"); var _constants2 = require("../../constants"); var _packages = require("../epm/packages"); var _registry = require("../epm/registry"); var _app_context = require("../app_context"); var _monitoring_permissions = require("./monitoring_permissions"); var _ = require("."); var _package_policies_to_agent_permissions = require("./package_policies_to_agent_permissions"); var _related_saved_objects = require("./related_saved_objects"); /* * 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. */ async function fetchAgentPolicy(soClient, id) { try { return await _agent_policy.agentPolicyService.get(soClient, id); } catch (err) { if (!err.isBoom || err.output.statusCode !== 404) { throw err; } } return null; } async function getFullAgentPolicy(soClient, id, options) { var _options$standalone, _agentPolicy$monitori, _agentPolicy$monitori2, _agentPolicy$monitori3, _agentPolicy$monitori4; const standalone = (_options$standalone = options === null || options === void 0 ? void 0 : options.standalone) !== null && _options$standalone !== void 0 ? _options$standalone : false; const agentPolicy = await fetchAgentPolicy(soClient, id); if (!agentPolicy) { return null; } const { outputs, proxies, dataOutput, fleetServerHosts, monitoringOutput, sourceUri } = await (0, _related_saved_objects.fetchRelatedSavedObjects)(soClient, agentPolicy); // Build up an in-memory object for looking up Package Info, so we don't have // call `getPackageInfo` for every single policy, which incurs performance costs const packageInfoCache = new Map(); for (const policy of agentPolicy.package_policies) { if (!policy.package || packageInfoCache.has((0, _registry.pkgToPkgKey)(policy.package))) { continue; } // Prime the cache w/ just the package key - we'll fetch all the package // info concurrently below packageInfoCache.set((0, _registry.pkgToPkgKey)(policy.package), {}); } // Fetch all package info concurrently await Promise.all(Array.from(packageInfoCache.keys()).map(async pkgKey => { const { pkgName, pkgVersion } = (0, _registry.splitPkgKey)(pkgKey); const packageInfo = await (0, _packages.getPackageInfo)({ savedObjectsClient: soClient, pkgName, pkgVersion }); packageInfoCache.set(pkgKey, packageInfo); })); const inputs = await (0, _.storedPackagePoliciesToAgentInputs)(agentPolicy.package_policies, packageInfoCache, getOutputIdForAgentPolicy(dataOutput)); const features = (agentPolicy.agent_features || []).reduce((acc, { name, ...featureConfig }) => { acc[name] = featureConfig; return acc; }, {}); const fullAgentPolicy = { id: agentPolicy.id, outputs: { ...outputs.reduce((acc, output) => { acc[getOutputIdForAgentPolicy(output)] = transformOutputToFullPolicyOutput(output, output.proxy_id ? proxies.find(proxy => output.proxy_id === proxy.id) : undefined, standalone); return acc; }, {}) }, inputs, secret_references: ((agentPolicy === null || agentPolicy === void 0 ? void 0 : agentPolicy.package_policies) || []).flatMap(policy => policy.secret_references || []), revision: agentPolicy.revision, agent: { download: { sourceURI: sourceUri }, monitoring: agentPolicy.monitoring_enabled && agentPolicy.monitoring_enabled.length > 0 ? { namespace: agentPolicy.namespace, use_output: getOutputIdForAgentPolicy(monitoringOutput), enabled: true, logs: agentPolicy.monitoring_enabled.includes(_constants.dataTypes.Logs), metrics: agentPolicy.monitoring_enabled.includes(_constants.dataTypes.Metrics) } : { enabled: false, logs: false, metrics: false }, features, protection: { enabled: agentPolicy.is_protected, uninstall_token_hash: '', signing_key: '' } }, signed: { data: '', signature: '' } }; const dataPermissions = (await (0, _package_policies_to_agent_permissions.storedPackagePoliciesToAgentPermissions)(packageInfoCache, agentPolicy.package_policies)) || {}; dataPermissions._elastic_agent_checks = { cluster: _package_policies_to_agent_permissions.DEFAULT_CLUSTER_PERMISSIONS }; const monitoringPermissions = await (0, _monitoring_permissions.getMonitoringPermissions)(soClient, { logs: (_agentPolicy$monitori = (_agentPolicy$monitori2 = agentPolicy.monitoring_enabled) === null || _agentPolicy$monitori2 === void 0 ? void 0 : _agentPolicy$monitori2.includes(_constants.dataTypes.Logs)) !== null && _agentPolicy$monitori !== void 0 ? _agentPolicy$monitori : false, metrics: (_agentPolicy$monitori3 = (_agentPolicy$monitori4 = agentPolicy.monitoring_enabled) === null || _agentPolicy$monitori4 === void 0 ? void 0 : _agentPolicy$monitori4.includes(_constants.dataTypes.Metrics)) !== null && _agentPolicy$monitori3 !== void 0 ? _agentPolicy$monitori3 : false }, agentPolicy.namespace); monitoringPermissions._elastic_agent_checks = { cluster: _package_policies_to_agent_permissions.DEFAULT_CLUSTER_PERMISSIONS }; // Only add permissions if output.type is "elasticsearch" fullAgentPolicy.output_permissions = Object.keys(fullAgentPolicy.outputs).reduce((outputPermissions, outputId) => { const output = fullAgentPolicy.outputs[outputId]; if (output && output.type === _constants.outputType.Elasticsearch) { const permissions = {}; if (outputId === getOutputIdForAgentPolicy(monitoringOutput)) { Object.assign(permissions, monitoringPermissions); } if (outputId === getOutputIdForAgentPolicy(dataOutput)) { Object.assign(permissions, dataPermissions); } outputPermissions[outputId] = permissions; } return outputPermissions; }, {}); // only add fleet server hosts if not in standalone if (!standalone && fleetServerHosts) { fullAgentPolicy.fleet = generateFleetConfig(fleetServerHosts, proxies); } // populate protection and signed properties const messageSigningService = _app_context.appContextService.getMessageSigningService(); if (messageSigningService && fullAgentPolicy.agent) { var _await$appContextServ, _appContextService$ge; const publicKey = await messageSigningService.getPublicKey(); const tokenHash = (_await$appContextServ = await ((_appContextService$ge = _app_context.appContextService.getUninstallTokenService()) === null || _appContextService$ge === void 0 ? void 0 : _appContextService$ge.getHashedTokenForPolicyId(fullAgentPolicy.id))) !== null && _await$appContextServ !== void 0 ? _await$appContextServ : ''; fullAgentPolicy.agent.protection = { enabled: agentPolicy.is_protected, uninstall_token_hash: tokenHash, signing_key: publicKey }; const dataToSign = { id: fullAgentPolicy.id, agent: { features, protection: fullAgentPolicy.agent.protection }, inputs: inputs.map(({ id: inputId, name, revision, type }) => ({ id: inputId, name, revision, type })) }; const { data: signedData, signature } = await messageSigningService.sign(dataToSign); fullAgentPolicy.signed = { data: signedData.toString('base64'), signature }; } if (agentPolicy.overrides) { return (0, _deepmerge.default)(fullAgentPolicy, agentPolicy.overrides); } return fullAgentPolicy; } function generateFleetConfig(fleetServerHosts, proxies) { const config = { hosts: fleetServerHosts.host_urls }; const fleetServerHostproxy = fleetServerHosts.proxy_id ? proxies.find(proxy => proxy.id === fleetServerHosts.proxy_id) : null; if (fleetServerHostproxy) { config.proxy_url = fleetServerHostproxy.url; if (fleetServerHostproxy.proxy_headers) { config.proxy_headers = fleetServerHostproxy.proxy_headers; } if (fleetServerHostproxy.certificate_authorities || fleetServerHostproxy.certificate || fleetServerHostproxy.certificate_key) { config.ssl = { renegotiation: 'never', verification_mode: '', ...(fleetServerHostproxy.certificate_authorities && { certificate_authorities: [fleetServerHostproxy.certificate_authorities] }), ...(fleetServerHostproxy.certificate && { certificate: fleetServerHostproxy.certificate }), ...(fleetServerHostproxy.certificate_key && { key: fleetServerHostproxy.certificate_key }) }; } } return config; } function transformOutputToFullPolicyOutput(output, proxy, standalone = false) { var _configJs$shipper; // eslint-disable-next-line @typescript-eslint/naming-convention const { config_yaml, type, hosts, ca_sha256, ca_trusted_fingerprint, ssl, shipper } = output; const configJs = config_yaml ? (0, _jsYaml.safeLoad)(config_yaml) : {}; // build logic to read config_yaml and transform it with the new shipper data const isShipperDisabled = !(configJs !== null && configJs !== void 0 && configJs.shipper) || (configJs === null || configJs === void 0 ? void 0 : (_configJs$shipper = configJs.shipper) === null || _configJs$shipper === void 0 ? void 0 : _configJs$shipper.enabled) === false; let shipperDiskQueueData = {}; let generalShipperData; let kafkaData = {}; if (type === _constants.outputType.Kafka) { /* eslint-disable @typescript-eslint/naming-convention */ const { client_id, version, key, compression, compression_level, username, password, sasl, partition, random, round_robin, hash, topics, headers, timeout, broker_timeout, required_acks } = output; const transformPartition = () => { if (!partition) return {}; switch (partition) { case 'random': return { random: { ...(random !== null && random !== void 0 && random.group_events ? { group_events: random.group_events } : { group_events: 1 }) } }; case 'round_robin': return { round_robin: { ...(round_robin !== null && round_robin !== void 0 && round_robin.group_events ? { group_events: round_robin.group_events } : { group_events: 1 }) } }; case 'hash': default: return { hash: { ...(hash !== null && hash !== void 0 && hash.hash ? { hash: hash.hash } : { hash: '' }) } }; } }; /* eslint-enable @typescript-eslint/naming-convention */ kafkaData = { client_id, version, key, compression, ...(compression === _constants.kafkaCompressionType.Gzip ? { compression_level } : {}), ...(username ? { username } : {}), ...(password ? { password } : {}), ...(sasl ? { sasl } : {}), partition: transformPartition(), topics: (topics !== null && topics !== void 0 ? topics : []).map(topic => { const { topic: topicName, ...rest } = topic; const whenKeys = Object.keys(rest); if (whenKeys.length === 0) { return { topic: topicName }; } if (rest.when && rest.when.condition) { const [keyName, value] = rest.when.condition.split(':'); return { topic: topicName, when: { [rest.when.type]: { [keyName.replace(/\s/g, '')]: value } } }; } }), headers: (headers !== null && headers !== void 0 ? headers : []).filter(item => item.key !== '' || item.value !== ''), timeout, broker_timeout, required_acks }; } if (shipper) { if (!isShipperDisabled) { shipperDiskQueueData = buildShipperQueueData(shipper); } /* eslint-disable @typescript-eslint/naming-convention */ const { loadbalance, compression_level, queue_flush_timeout, max_batch_bytes, mem_queue_events } = shipper; /* eslint-enable @typescript-eslint/naming-convention */ generalShipperData = { loadbalance, compression_level, queue_flush_timeout, max_batch_bytes, mem_queue_events }; } const newOutput = { ...configJs, ...shipperDiskQueueData, type, hosts, ...kafkaData, ...(!isShipperDisabled ? generalShipperData : {}), ...(ca_sha256 ? { ca_sha256 } : {}), ...(ssl ? { ssl } : {}), ...(ca_trusted_fingerprint ? { 'ssl.ca_trusted_fingerprint': ca_trusted_fingerprint } : {}) }; if (proxy) { newOutput.proxy_url = proxy.url; if (proxy.proxy_headers) { newOutput.proxy_headers = proxy.proxy_headers; } if (proxy.certificate_authorities) { if (!newOutput.ssl) { newOutput.ssl = {}; } if (!newOutput.ssl.certificate_authorities) { newOutput.ssl.certificate_authorities = []; } newOutput.ssl.certificate_authorities.push(proxy.certificate_authorities); } if (proxy.certificate) { if (!newOutput.ssl) { newOutput.ssl = {}; } newOutput.ssl.certificate = proxy.certificate; } if (proxy.certificate_key) { if (!newOutput.ssl) { newOutput.ssl = {}; } newOutput.ssl.key = proxy.certificate_key; } } if (output.type === _constants.outputType.Elasticsearch && standalone) { newOutput.username = '${ES_USERNAME}'; newOutput.password = '${ES_PASSWORD}'; } return newOutput; } /** * Get id used in full agent policy (sent to the agents) * we use "default" for the default policy to avoid breaking changes */ function getOutputIdForAgentPolicy(output) { if (output.is_default) { return _constants2.DEFAULT_OUTPUT.name; } return output.id; } /* eslint-disable @typescript-eslint/naming-convention */ function buildShipperQueueData(shipper) { const { disk_queue_enabled, disk_queue_path, disk_queue_max_size, disk_queue_compression_enabled } = shipper; if (!disk_queue_enabled) return {}; return { shipper: { queue: { disk: { path: disk_queue_path, max_size: disk_queue_max_size, use_compression: disk_queue_compression_enabled } } } }; } /* eslint-enable @typescript-eslint/naming-convention */