From 22991c739d5c0c975e53a8d7d9481dc78ecfa360 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Fri, 25 Oct 2024 12:00:59 -0400 Subject: [PATCH 01/13] Register new test suite with buildkite --- .buildkite/ftr_security_serverless_configs.yml | 1 + .buildkite/ftr_security_stateful_configs.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.buildkite/ftr_security_serverless_configs.yml b/.buildkite/ftr_security_serverless_configs.yml index 22d139103482..47527aca7953 100644 --- a/.buildkite/ftr_security_serverless_configs.yml +++ b/.buildkite/ftr_security_serverless_configs.yml @@ -96,6 +96,7 @@ enabled: - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/metadata/trial_license_complete_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/package/trial_license_complete_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy_response/trial_license_complete_tier/configs/serverless.config.ts + - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/resolver/trial_license_complete_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/response_actions/trial_license_complete_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/spaces/trial_license_complete_tier/configs/serverless.config.ts diff --git a/.buildkite/ftr_security_stateful_configs.yml b/.buildkite/ftr_security_stateful_configs.yml index aa37c6f52fb8..9c0817778efd 100644 --- a/.buildkite/ftr_security_stateful_configs.yml +++ b/.buildkite/ftr_security_stateful_configs.yml @@ -83,6 +83,7 @@ enabled: - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/metadata/trial_license_complete_tier/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/package/trial_license_complete_tier/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy_response/trial_license_complete_tier/configs/ess.config.ts + - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/resolver/trial_license_complete_tier/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/response_actions/trial_license_complete_tier/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/edr_workflows/spaces/trial_license_complete_tier/configs/ess.config.ts From f63f7b5dc1bee2612885f93d3b1a7e028609f8a8 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Fri, 25 Oct 2024 12:01:46 -0400 Subject: [PATCH 02/13] Move `buildIndexNameWithNamespace()` to top-level common directory so that it can be reused in FTR --- .../endpoint/utils/index_name_utilities.ts | 34 +++++++++++++++++++ .../handlers/create_policy_datastreams.ts | 17 +--------- 2 files changed, 35 insertions(+), 16 deletions(-) create mode 100644 x-pack/plugins/security_solution/common/endpoint/utils/index_name_utilities.ts diff --git a/x-pack/plugins/security_solution/common/endpoint/utils/index_name_utilities.ts b/x-pack/plugins/security_solution/common/endpoint/utils/index_name_utilities.ts new file mode 100644 index 000000000000..80db5392f653 --- /dev/null +++ b/x-pack/plugins/security_solution/common/endpoint/utils/index_name_utilities.ts @@ -0,0 +1,34 @@ +/* + * 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. + */ + +/** + * Builds an index name that includes the `namespace` using the provided index name prefix or pattern. + * + * @param indexNamePrefixOrPattern + * @param namespace + * + * @example + * + * buildIndexNameWithNamespace('logs-foo.bar-*', 'default'); // == 'logs-foo.bar-default' + * buildIndexNameWithNamespace('logs-foo.bar', 'default'); // == 'logs-foo.bar-default' + * buildIndexNameWithNamespace('logs-foo.bar-', 'default'); // == 'logs-foo.bar-default' + */ +export const buildIndexNameWithNamespace = ( + indexNamePrefixOrPattern: string, + namespace: string +): string => { + if (indexNamePrefixOrPattern.endsWith('*')) { + const hasDash = indexNamePrefixOrPattern.endsWith('-*'); + return `${indexNamePrefixOrPattern.substring(0, indexNamePrefixOrPattern.length - 1)}${ + hasDash ? '' : '-' + }${namespace}`; + } + + return `${indexNamePrefixOrPattern}${ + indexNamePrefixOrPattern.endsWith('-') ? '' : '-' + }${namespace}`; +}; diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_policy_datastreams.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_policy_datastreams.ts index a113c68e4132..4a759987245e 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_policy_datastreams.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_policy_datastreams.ts @@ -6,6 +6,7 @@ */ import pMap from 'p-map'; +import { buildIndexNameWithNamespace } from '../../../common/endpoint/utils/index_name_utilities'; import type { EndpointAppContextService } from '../../endpoint/endpoint_app_context_services'; import { catchAndWrapError } from '../../endpoint/utils'; import type { SimpleMemCacheInterface } from '../../endpoint/lib/simple_mem_cache'; @@ -17,22 +18,6 @@ import { import { DEFAULT_DIAGNOSTIC_INDEX } from '../../lib/telemetry/constants'; import { stringify } from '../../endpoint/utils/stringify'; -const buildIndexNameWithNamespace = ( - indexNamePrefixOrPattern: string, - namespace: string -): string => { - if (indexNamePrefixOrPattern.endsWith('*')) { - const hasDash = indexNamePrefixOrPattern.endsWith('-*'); - return `${indexNamePrefixOrPattern.substring(0, indexNamePrefixOrPattern.length - 1)}${ - hasDash ? '' : '-' - }${namespace}`; - } - - return `${indexNamePrefixOrPattern}${ - indexNamePrefixOrPattern.endsWith('-') ? '' : '-' - }${namespace}`; -}; - const cache = new SimpleMemCache({ // Cache of created Datastreams last for 12h, at which point it is checked again. // This is just a safeguard case (for whatever reason) the index is deleted From 3ce19da5df6a549a0ba39a973a3731c187555c4d Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Fri, 25 Oct 2024 12:10:15 -0400 Subject: [PATCH 03/13] unit tests for index name utilities --- .../utils/index_name_utilities.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 x-pack/plugins/security_solution/common/endpoint/utils/index_name_utilities.test.ts diff --git a/x-pack/plugins/security_solution/common/endpoint/utils/index_name_utilities.test.ts b/x-pack/plugins/security_solution/common/endpoint/utils/index_name_utilities.test.ts new file mode 100644 index 000000000000..25eb35bf8887 --- /dev/null +++ b/x-pack/plugins/security_solution/common/endpoint/utils/index_name_utilities.test.ts @@ -0,0 +1,19 @@ +/* + * 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. + */ + +import { buildIndexNameWithNamespace } from './index_name_utilities'; + +describe('index name utilities', () => { + describe('buildIndexNameWithNamespace()', () => { + test.each(['logs-endpoint.foo', 'logs-endpoint.foo-', 'logs-endpoint.foo-*'])( + `should build correct index name for: %s`, + (prefix) => { + expect(buildIndexNameWithNamespace(prefix, 'bar')).toEqual('logs-endpoint.foo-bar'); + } + ); + }); +}); From 3883570e1c5cd6f7f4891ea418cd90fdde38f122 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Fri, 25 Oct 2024 12:28:32 -0400 Subject: [PATCH 04/13] Move `DEFAULT_DIAGNOSTIC_INDEX_PATTERN` to top level `common/endpoint/constants` for reuse --- .../plugins/security_solution/common/endpoint/constants.ts | 3 +++ .../fleet_integration/handlers/create_policy_datastreams.ts | 4 ++-- .../server/integration_tests/lib/telemetry_helpers.ts | 6 +++--- .../security_solution/server/lib/telemetry/constants.ts | 2 -- .../security_solution/server/lib/telemetry/receiver.ts | 4 ++-- .../server/lib/telemetry/tasks/timelines_diagnostic.ts | 5 +++-- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/constants.ts b/x-pack/plugins/security_solution/common/endpoint/constants.ts index 534d7e5c2b8a..19aa53eca664 100644 --- a/x-pack/plugins/security_solution/common/endpoint/constants.ts +++ b/x-pack/plugins/security_solution/common/endpoint/constants.ts @@ -55,6 +55,9 @@ export const telemetryIndexPattern = 'metrics-endpoint.telemetry-*'; export const ENDPOINT_HEARTBEAT_INDEX = '.logs-endpoint.heartbeat-default'; export const ENDPOINT_HEARTBEAT_INDEX_PATTERN = '.logs-endpoint.heartbeat-*'; +// Endpoint diagnostics index +export const DEFAULT_DIAGNOSTIC_INDEX_PATTERN = '.logs-endpoint.diagnostic.collection-*' as const; + // File storage indexes supporting endpoint Upload/download export const FILE_STORAGE_METADATA_INDEX = getFileMetadataIndexName('endpoint'); export const FILE_STORAGE_DATA_INDEX = getFileDataIndexName('endpoint'); diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_policy_datastreams.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_policy_datastreams.ts index 4a759987245e..e94bc71cd4fa 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_policy_datastreams.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_policy_datastreams.ts @@ -12,10 +12,10 @@ import { catchAndWrapError } from '../../endpoint/utils'; import type { SimpleMemCacheInterface } from '../../endpoint/lib/simple_mem_cache'; import { SimpleMemCache } from '../../endpoint/lib/simple_mem_cache'; import { + DEFAULT_DIAGNOSTIC_INDEX_PATTERN, ENDPOINT_ACTION_RESPONSES_DS, ENDPOINT_HEARTBEAT_INDEX_PATTERN, } from '../../../common/endpoint/constants'; -import { DEFAULT_DIAGNOSTIC_INDEX } from '../../lib/telemetry/constants'; import { stringify } from '../../endpoint/utils/stringify'; const cache = new SimpleMemCache({ @@ -66,7 +66,7 @@ export const createPolicyDataStreamsIfNeeded: PolicyDataStreamsCreator = async ( const indicesToCreate: string[] = Array.from( Object.values(policyNamespaces.integrationPolicy).reduce>((acc, namespaceList) => { for (const namespace of namespaceList) { - acc.add(buildIndexNameWithNamespace(DEFAULT_DIAGNOSTIC_INDEX, namespace)); + acc.add(buildIndexNameWithNamespace(DEFAULT_DIAGNOSTIC_INDEX_PATTERN, namespace)); acc.add(buildIndexNameWithNamespace(ENDPOINT_ACTION_RESPONSES_DS, namespace)); if (endpointServices.isServerless()) { diff --git a/x-pack/plugins/security_solution/server/integration_tests/lib/telemetry_helpers.ts b/x-pack/plugins/security_solution/server/integration_tests/lib/telemetry_helpers.ts index d83ff1e910ca..a36d5e1be38d 100644 --- a/x-pack/plugins/security_solution/server/integration_tests/lib/telemetry_helpers.ts +++ b/x-pack/plugins/security_solution/server/integration_tests/lib/telemetry_helpers.ts @@ -30,6 +30,7 @@ import { packagePolicyService } from '@kbn/fleet-plugin/server/services'; import { ENDPOINT_ARTIFACT_LISTS } from '@kbn/securitysolution-list-constants'; import { DETECTION_TYPE, NAMESPACE_TYPE } from '@kbn/lists-plugin/common/constants.mock'; +import { DEFAULT_DIAGNOSTIC_INDEX_PATTERN } from '../../../common/endpoint/constants'; import { bulkInsert, updateTimestamps } from './helpers'; import { TelemetryEventsSender } from '../../lib/telemetry/sender'; import type { @@ -40,7 +41,6 @@ import type { SecurityTelemetryTask } from '../../lib/telemetry/task'; import { Plugin as SecuritySolutionPlugin } from '../../plugin'; import { AsyncTelemetryEventsSender } from '../../lib/telemetry/async_sender'; import { type ITelemetryReceiver, TelemetryReceiver } from '../../lib/telemetry/receiver'; -import { DEFAULT_DIAGNOSTIC_INDEX } from '../../lib/telemetry/constants'; import mockEndpointAlert from '../__mocks__/endpoint-alert.json'; import mockedRule from '../__mocks__/rule.json'; import fleetAgents from '../__mocks__/fleet-agents.json'; @@ -147,7 +147,7 @@ export function getTelemetryTask( } export async function createMockedEndpointAlert(esClient: ElasticsearchClient) { - const index = `${DEFAULT_DIAGNOSTIC_INDEX.replace('-*', '')}-001`; + const index = `${DEFAULT_DIAGNOSTIC_INDEX_PATTERN.replace('-*', '')}-001`; await esClient.indices.create({ index, body: { settings: { hidden: true } } }); @@ -223,7 +223,7 @@ export async function dropEndpointIndices(esClient: ElasticsearchClient) { } export async function cleanupMockedEndpointAlerts(esClient: ElasticsearchClient) { - const index = `${DEFAULT_DIAGNOSTIC_INDEX.replace('-*', '')}-001`; + const index = `${DEFAULT_DIAGNOSTIC_INDEX_PATTERN.replace('-*', '')}-001`; await esClient.indices.delete({ index }).catch(() => { // ignore errors diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/constants.ts b/x-pack/plugins/security_solution/server/lib/telemetry/constants.ts index 8e50e4590a72..50e0e0be47cd 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/constants.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/constants.ts @@ -27,8 +27,6 @@ export const INSIGHTS_CHANNEL = 'security-insights-v1'; export const TASK_METRICS_CHANNEL = 'task-metrics'; -export const DEFAULT_DIAGNOSTIC_INDEX = '.logs-endpoint.diagnostic.collection-*' as const; - export const DEFAULT_ADVANCED_POLICY_CONFIG_SETTINGS = { linux: { advanced: { diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts b/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts index 22f85d19c83d..4d2ff971eeb6 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts @@ -48,6 +48,7 @@ import type { } from '@kbn/fleet-plugin/server'; import type { ExceptionListClient } from '@kbn/lists-plugin/server'; import moment from 'moment'; +import { DEFAULT_DIAGNOSTIC_INDEX_PATTERN } from '../../../common/endpoint/constants'; import type { ExperimentalFeatures } from '../../../common'; import type { EndpointAppContextService } from '../../endpoint/endpoint_app_context_services'; import { @@ -85,7 +86,6 @@ import type { import { telemetryConfiguration } from './configuration'; import { ENDPOINT_METRICS_INDEX } from '../../../common/constants'; import { PREBUILT_RULES_PACKAGE_NAME } from '../../../common/detection_engine/constants'; -import { DEFAULT_DIAGNOSTIC_INDEX } from './constants'; import type { TelemetryLogger } from './telemetry_logger'; export interface ITelemetryReceiver { @@ -546,7 +546,7 @@ export class TelemetryReceiver implements ITelemetryReceiver { to: executeTo, } as LogMeta); - let pitId = await this.openPointInTime(DEFAULT_DIAGNOSTIC_INDEX); + let pitId = await this.openPointInTime(DEFAULT_DIAGNOSTIC_INDEX_PATTERN); let fetchMore = true; let searchAfter: SortResults | undefined; diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/tasks/timelines_diagnostic.ts b/x-pack/plugins/security_solution/server/lib/telemetry/tasks/timelines_diagnostic.ts index 35f5abeac10a..ec401a093c34 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/tasks/timelines_diagnostic.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/tasks/timelines_diagnostic.ts @@ -6,11 +6,12 @@ */ import type { Logger } from '@kbn/core/server'; +import { DEFAULT_DIAGNOSTIC_INDEX_PATTERN } from '../../../../common/endpoint/constants'; import type { ITelemetryEventsSender } from '../sender'; import type { ITelemetryReceiver } from '../receiver'; import type { TaskExecutionPeriod } from '../task'; import type { ITaskMetricsService } from '../task_metrics.types'; -import { DEFAULT_DIAGNOSTIC_INDEX, TELEMETRY_CHANNEL_TIMELINE } from '../constants'; +import { TELEMETRY_CHANNEL_TIMELINE } from '../constants'; import { ranges, TelemetryTimelineFetcher, newTelemetryLogger } from '../helpers'; export function createTelemetryDiagnosticTimelineTaskConfig() { @@ -43,7 +44,7 @@ export function createTelemetryDiagnosticTimelineTaskConfig() { const { rangeFrom, rangeTo } = ranges(taskExecutionPeriod); const alerts = await receiver.fetchTimelineAlerts( - DEFAULT_DIAGNOSTIC_INDEX, + DEFAULT_DIAGNOSTIC_INDEX_PATTERN, rangeFrom, rangeTo ); From 8c7049a227070563cbf0666afe675dff2cb60171 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Fri, 25 Oct 2024 15:30:57 -0400 Subject: [PATCH 05/13] Additional methods added to the fleet scripting services --- .../scripts/endpoint/common/fleet_services.ts | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts index 92c13a521ed2..2f4324be3b4d 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts @@ -21,10 +21,12 @@ import type { GetAgentsResponse, GetInfoResponse, GetOneAgentPolicyResponse, + GetOnePackagePolicyResponse, GetPackagePoliciesRequest, GetPackagePoliciesResponse, PackagePolicy, PostFleetSetupResponse, + UpdatePackagePolicyResponse, } from '@kbn/fleet-plugin/common'; import { AGENT_API_ROUTES, @@ -39,6 +41,7 @@ import { PACKAGE_POLICY_API_ROUTES, PACKAGE_POLICY_SAVED_OBJECT_TYPE, SETUP_API_ROUTE, + packagePolicyRouteService, } from '@kbn/fleet-plugin/common'; import type { ToolingLog } from '@kbn/tooling-log'; import type { KbnClient } from '@kbn/test'; @@ -57,11 +60,15 @@ import type { GetEnrollmentAPIKeysResponse, GetOutputsResponse, PostAgentUnenrollResponse, + UpdateAgentPolicyRequest, + UpdateAgentPolicyResponse, } from '@kbn/fleet-plugin/common/types'; import semver from 'semver'; import axios from 'axios'; import { userInfo } from 'os'; import pRetry from 'p-retry'; +import { AgentPolicyBaseSchema } from '@kbn/fleet-plugin/server/types'; +import { getPolicyDataForUpdate } from '../../../common/endpoint/service/policy'; import { fetchActiveSpace } from './spaces'; import { fetchKibanaStatus } from '../../../common/endpoint/utils/kibana_status'; import { isFleetServerRunning } from './fleet_server/fleet_server_services'; @@ -76,6 +83,7 @@ import { } from '../../../common/endpoint/data_loaders/utils'; import { catchAxiosErrorFormatAndThrow } from '../../../common/endpoint/format_axios_error'; import { FleetAgentGenerator } from '../../../common/endpoint/data_generators/fleet_agent_generator'; +import type { PolicyData } from '../../../common/endpoint/types'; const fleetGenerator = new FleetAgentGenerator(); const CURRENT_USERNAME = userInfo().username.toLowerCase(); @@ -1369,3 +1377,93 @@ export const enableFleetSpaceAwareness = memoize(async (kbnClient: KbnClient): P }) .catch(catchAxiosErrorFormatAndThrow); }); + +/** + * Fetches a single integratino policy by id + * @param kbnClient + * @param policyId + */ +export const fetchIntegrationPolicy = async ( + kbnClient: KbnClient, + policyId: string +): Promise => { + return kbnClient + .request({ + path: packagePolicyRouteService.getInfoPath(policyId), + method: 'GET', + headers: { 'elastic-api-version': '2023-10-31' }, + }) + .catch(catchAxiosErrorFormatAndThrow) + .then((response) => response.data.item); +}; + +/** + * Update a fleet integration policy (aka: package policy) + * @param kbnClient + */ +export const updateIntegrationPolicy = async ( + kbnClient: KbnClient, + /** The Integration policy id */ + id: string, + policyData: Partial, + /** If set to `true`, then `policyData` can be a partial set of updates and not the full policy data */ + patch: boolean = false +): Promise => { + let fullPolicyData = policyData; + + if (patch) { + const currentSavedPolicy = await fetchIntegrationPolicy(kbnClient, id); + fullPolicyData = getPolicyDataForUpdate(currentSavedPolicy as PolicyData); + Object.assign(fullPolicyData, policyData); + } + + return kbnClient + .request({ + path: packagePolicyRouteService.getUpdatePath(id), + method: 'PUT', + body: fullPolicyData, + headers: { 'elastic-api-version': '2023-10-31' }, + }) + .catch(catchAxiosErrorFormatAndThrow) + .then((response) => response.data.item); +}; + +/** + * Updates a Fleet agent policy + * @param kbnClient + * @param id + * @param policyData + * @param patch + */ +export const updateAgentPolicy = async ( + kbnClient: KbnClient, + /** Fleet Agent Policy ID */ + id: string, + /** The updated agent policy data. Could be a `partial` update if `patch` arguments below is true */ + policyData: Partial, + /** + * If set to `true`, the `policyData` provided on input will first be merged with the latest version + * of the policy and then the updated applied + */ + patch: boolean = false +): Promise => { + let fullPolicyData = policyData; + + if (patch) { + const currentSavedPolicy = await fetchAgentPolicy(kbnClient, id); + + fullPolicyData = pick(currentSavedPolicy, Object.keys(AgentPolicyBaseSchema)); + delete fullPolicyData.id; + Object.assign(fullPolicyData, policyData); + } + + return kbnClient + .request({ + path: agentPolicyRouteService.getUpdatePath(id), + method: 'PUT', + body: fullPolicyData, + headers: { 'elastic-api-version': '2023-10-31' }, + }) + .catch(catchAxiosErrorFormatAndThrow) + .then((response) => response.data.item); +}; From 88c9f68411df67d3d85acca45ac08684b1ce13d3 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Fri, 25 Oct 2024 15:31:49 -0400 Subject: [PATCH 06/13] Improve FTR policy service `createPolicy()` to allow for policy value overrides --- .../services/endpoint_policy.ts | 61 ++++++++++++------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts b/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts index 335328db08ce..5b7fd8b86f28 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts @@ -27,19 +27,19 @@ import { pkgKeyFromPackageInfo } from '@kbn/fleet-plugin/public/services/pkg_key import { EndpointError } from '@kbn/security-solution-plugin/common/endpoint/errors'; import { FtrProviderContext } from '../configs/ftr_provider_context'; -const INGEST_API_ROOT = '/api/fleet'; -const INGEST_API_AGENT_POLICIES = `${INGEST_API_ROOT}/agent_policies`; -const INGEST_API_AGENT_POLICIES_DELETE = `${INGEST_API_AGENT_POLICIES}/delete`; -const INGEST_API_PACKAGE_POLICIES = `${INGEST_API_ROOT}/package_policies`; -const INGEST_API_PACKAGE_POLICIES_DELETE = `${INGEST_API_PACKAGE_POLICIES}/delete`; +const FLEET_API_ROOT = '/api/fleet'; +const FLEET_API_AGENT_POLICIES = `${FLEET_API_ROOT}/agent_policies`; +const FLEET_API_AGENT_POLICIES_DELETE = `${FLEET_API_AGENT_POLICIES}/delete`; +const FLEET_API_PACKAGE_POLICIES = `${FLEET_API_ROOT}/package_policies`; +const FLEET_API_PACKAGE_POLICIES_DELETE = `${FLEET_API_PACKAGE_POLICIES}/delete`; /** * Holds information about the test resources created to support an Endpoint Policy */ export interface PolicyTestResourceInfo { - /** The Ingest agent policy created */ + /** The Fleet agent policy created */ agentPolicy: Immutable; - /** The Ingest Package Policy created and added to agent policy. + /** The Fleet Package Policy created and added to agent policy. * This is where Endpoint Policy is stored. */ packagePolicy: Immutable; @@ -55,6 +55,7 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC const supertest = getService('supertest'); const log = getService('log'); const retry = getService('retry'); + const kbnClient = getService('kibanaServer'); const logSupertestApiErrorAndThrow = (message: string, error: any): never => { const responseBody = error?.response?.body; @@ -87,7 +88,7 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC .expect(200) .catch((error) => { return logSupertestApiErrorAndThrow( - `Unable to retrieve Endpoint package via Ingest!`, + `Unable to retrieve Endpoint package via Fleet!`, error ); }) @@ -139,7 +140,7 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC let fullAgentPolicy: GetFullAgentPolicyResponse['item']; try { const apiResponse: { body: GetFullAgentPolicyResponse } = await supertest - .get(`${INGEST_API_AGENT_POLICIES}/${agentPolicyId}/full`) + .get(`${FLEET_API_AGENT_POLICIES}/${agentPolicyId}/full`) .expect(200); fullAgentPolicy = apiResponse.body.item; @@ -151,10 +152,16 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC }, /** - * Creates an Ingest Agent policy and adds to it the Endpoint Package Policy that + * Creates a Fleet Agent policy and adds to it the Endpoint Package Policy that * stores the Policy configuration data */ - async createPolicy(): Promise { + async createPolicy({ + agentPolicyOverrides = {}, + integrationPolicyOverrides = {}, + }: Partial<{ + agentPolicyOverrides: Partial; + integrationPolicyOverrides: Partial; + }> = {}): Promise { // create Agent Policy let agentPolicy: CreateAgentPolicyResponse['item']; try { @@ -162,15 +169,16 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC name: `East Coast ${uuidv4()}`, description: 'East Coast call center', namespace: 'default', + ...agentPolicyOverrides, }; const { body: createResponse }: { body: CreateAgentPolicyResponse } = await supertest - .post(INGEST_API_AGENT_POLICIES) + .post(FLEET_API_AGENT_POLICIES) .set('kbn-xsrf', 'xxx') .send(newAgentPolicyData) .expect(200); agentPolicy = createResponse.item; } catch (error) { - return logSupertestApiErrorAndThrow(`Unable to create Agent Policy via Ingest!`, error); + return logSupertestApiErrorAndThrow(`Unable to create Agent Policy via Fleet!`, error); } // Retrieve the Endpoint package information @@ -210,15 +218,16 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC title: endpointPackageInfo?.title ?? '', version: endpointPackageInfo?.version ?? '', }, + ...integrationPolicyOverrides, }; const { body: createResponse }: { body: CreatePackagePolicyResponse } = await supertest - .post(INGEST_API_PACKAGE_POLICIES) + .post(FLEET_API_PACKAGE_POLICIES) .set('kbn-xsrf', 'xxx') .send(newPackagePolicyData) .expect(200); packagePolicy = createResponse.item; } catch (error) { - return logSupertestApiErrorAndThrow(`Unable to create Package Policy via Ingest!`, error); + return logSupertestApiErrorAndThrow(`Unable to create Package Policy via Fleet!`, error); } log.info( @@ -237,12 +246,16 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC packagePolicyIds: [packagePolicy.id], }; await supertest - .post(INGEST_API_PACKAGE_POLICIES_DELETE) + .post(FLEET_API_PACKAGE_POLICIES_DELETE) .set('kbn-xsrf', 'xxx') .send(deletePackagePolicyData) .expect(200); + log.info(`Fleet Endpoint integration policy deleted: ${packagePolicy.id}`); } catch (error) { - logSupertestApiErrorAndThrow('Unable to delete Package Policy via Ingest!', error); + logSupertestApiErrorAndThrow( + `Unable to delete Endpoint Integration Policy [${packagePolicy.id}] via Fleet!`, + error + ); } // Delete Agent Policy @@ -251,12 +264,16 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC agentPolicyId: agentPolicy.id, }; await supertest - .post(INGEST_API_AGENT_POLICIES_DELETE) + .post(FLEET_API_AGENT_POLICIES_DELETE) .set('kbn-xsrf', 'xxx') .send(deleteAgentPolicyData) .expect(200); + log.info(`Fleet Agent policy deleted: ${agentPolicy.id}`); } catch (error) { - logSupertestApiErrorAndThrow('Unable to delete Agent Policy via Ingest!', error); + logSupertestApiErrorAndThrow( + `Unable to delete Agent Policy [${agentPolicy.id}] via Fleet!`, + error + ); } }, }; @@ -271,7 +288,7 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC try { const { body: packagePoliciesResponse }: { body: GetPackagePoliciesResponse } = await supertest - .get(INGEST_API_PACKAGE_POLICIES) + .get(FLEET_API_PACKAGE_POLICIES) .set('kbn-xsrf', 'xxx') .query({ kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.name: ${name}` }) .send() @@ -297,12 +314,12 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC packagePolicyIds: [packagePolicyList[0].id], }; await supertest - .post(INGEST_API_PACKAGE_POLICIES_DELETE) + .post(FLEET_API_PACKAGE_POLICIES_DELETE) .set('kbn-xsrf', 'xxx') .send(deletePackagePolicyData) .expect(200); } catch (error) { - logSupertestApiErrorAndThrow('Unable to delete Package Policy via Ingest!', error); + logSupertestApiErrorAndThrow('Unable to delete Package Policy via Fleet!', error); } }, }; From e9f8aaae0740f185ede634d15ada391c89e01ba8 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Fri, 25 Oct 2024 15:41:31 -0400 Subject: [PATCH 07/13] FTR test suite for policy (API) that validates indcies are created --- .../configs/ess.config.ts | 22 +++ .../configs/serverless.config.ts | 22 +++ .../datastream_index_creation.ts | 133 ++++++++++++++++++ .../trial_license_complete_tier/index.ts | 56 ++++++++ 4 files changed, 233 insertions(+) create mode 100644 x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/configs/ess.config.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/configs/serverless.config.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/datastream_index_creation.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/index.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/configs/ess.config.ts new file mode 100644 index 000000000000..bee23188b35a --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/configs/ess.config.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile( + require.resolve('../../../../../config/ess/config.base.edr_workflows.trial') + ); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('..')], + junit: { + reportName: 'EDR Workflows API - Policy Tests - ESS Env - Trial License', + }, + }; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/configs/serverless.config.ts new file mode 100644 index 000000000000..ea2e2ce875ad --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/configs/serverless.config.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile( + require.resolve('../../../../../config/serverless/config.base.edr_workflows') + ); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('..')], + junit: { + reportName: 'EDR Workflows API - Policy Tests - Serverless Env - Complete', + }, + }; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/datastream_index_creation.ts b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/datastream_index_creation.ts new file mode 100644 index 000000000000..7b722ec66828 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/datastream_index_creation.ts @@ -0,0 +1,133 @@ +/* + * 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. + */ + +import expect from '@kbn/expect'; +import { + DEFAULT_DIAGNOSTIC_INDEX_PATTERN, + ENDPOINT_ACTION_RESPONSES_DS, + ENDPOINT_HEARTBEAT_INDEX_PATTERN, +} from '@kbn/security-solution-plugin/common/endpoint/constants'; +import { buildIndexNameWithNamespace } from '@kbn/security-solution-plugin/common/endpoint/utils/index_name_utilities'; +import { + updateAgentPolicy, + updateIntegrationPolicy, +} from '@kbn/security-solution-plugin/scripts/endpoint/common/fleet_services'; +import { PolicyTestResourceInfo } from '../../../../../security_solution_endpoint/services/endpoint_policy'; +import { FtrProviderContext } from '../../../../ftr_provider_context_edr_workflows'; + +export default function ({ getService }: FtrProviderContext) { + const endpointPolicyTestResources = getService('endpointPolicyTestResources'); + const esClient = getService('es'); + const kbnClient = getService('kibanaServer'); + const log = getService('log'); + const retry = getService('retry'); + const config = getService('config'); + const isServerless = config.get('serverless'); + + // FIXME:PT Remove @skipInServerlessMKI and enable it for MKI + describe('@ess @serverless @skipInServerlessMKI Creation of DOT indices for elastic defend policies', function () { + let testData: PolicyTestResourceInfo; + + const getExpectedIndexList = (namespace: string): string[] => { + const indexList = [ + buildIndexNameWithNamespace(ENDPOINT_ACTION_RESPONSES_DS, namespace), + buildIndexNameWithNamespace(DEFAULT_DIAGNOSTIC_INDEX_PATTERN, namespace), + ]; + + if (isServerless) { + indexList.push(buildIndexNameWithNamespace(ENDPOINT_HEARTBEAT_INDEX_PATTERN, namespace)); + } + + return indexList; + }; + + beforeEach(async () => { + testData = await endpointPolicyTestResources.createPolicy({ + // Endpoint policy inherits namespace from Agent policy + integrationPolicyOverrides: { namespace: undefined }, + }); + }); + + afterEach(async () => { + if (testData) { + await testData.cleanup(); + // @ts-expect-error + testData = undefined; + } + }); + + it('should create indices when endpoint integration policy is created', async () => { + for (const indexName of getExpectedIndexList('default')) { + log.debug(`Checking that [${indexName}] exists`); + // The creation of the indices is done in the background and may not be done by + // the time the API call that created/updated the policy in fleet is returned - thus + // we use retry logic below + await retry.try(async () => { + expect(await esClient.indices.exists({ index: indexName })).to.be(true); + }); + } + }); + + it('should create new indices when endpoint policy is updated with new namespace', async () => { + const namespace = Math.random().toString(32).substring(2); + await updateIntegrationPolicy(kbnClient, testData.packagePolicy.id, { namespace }, true); + + for (const indexName of getExpectedIndexList(namespace)) { + log.debug(`Checking that [${indexName}] exists`); + await retry.try(async () => { + expect(await esClient.indices.exists({ index: indexName })).to.be(true); + }); + } + }); + + it('should create new indices when agent policy is updated with new namespace', async () => { + const namespace = Math.random().toString(32).substring(2); + await updateAgentPolicy(kbnClient, testData.agentPolicy.id, { namespace }, true); + + for (const indexName of getExpectedIndexList(namespace)) { + log.debug(`Checking that [${indexName}] exists`); + await retry.try(async () => { + expect(await esClient.indices.exists({ index: indexName })).to.be(true); + }); + } + }); + + it('should NOT create indices when agent policy is updated if endpoint policy explicitly has a namespace defined', async () => { + const namespace = Math.random().toString(32).substring(2); + await updateIntegrationPolicy(kbnClient, testData.packagePolicy.id, { namespace }, true); + + for (const indexName of getExpectedIndexList(namespace)) { + log.debug(`Checking that [${indexName}] exists`); + await retry.try(async () => { + expect(await esClient.indices.exists({ index: indexName })).to.be(true); + }); + } + + // Now update agent policy with new namespace and check that indices are NOT created + const namespace2 = Math.random().toString(32).substring(2); + await updateAgentPolicy(kbnClient, testData.agentPolicy.id, { namespace: namespace2 }, true); + + // Delay just a few seconds to ensure policy index logic has executed + await new Promise(async (resolve, reject) => { + try { + setTimeout(() => { + resolve(); + }, 5000); + } catch (error) { + reject(error); + } + }); + + for (const indexName of getExpectedIndexList(namespace2)) { + log.debug(`Checking that [${indexName}] does NOT exists`); + await retry.try(async () => { + expect(await esClient.indices.exists({ index: indexName })).to.be(false); + }); + } + }); + }); +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/index.ts b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/index.ts new file mode 100644 index 000000000000..2d96bd3edceb --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/index.ts @@ -0,0 +1,56 @@ +/* + * 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. + */ +import { getRegistryUrl as getRegistryUrlFromIngest } from '@kbn/fleet-plugin/server'; +import { isServerlessKibanaFlavor } from '@kbn/security-solution-plugin/common/endpoint/utils/kibana_status'; +import { FtrProviderContext } from '../../../../ftr_provider_context_edr_workflows'; +import { ROLE } from '../../../../config/services/security_solution_edr_workflows_roles_users'; + +export default function endpointAPIIntegrationTests(providerContext: FtrProviderContext) { + const { loadTestFile, getService } = providerContext; + + describe('Endpoint Policv', function () { + const ingestManager = getService('ingestManager'); + const rolesUsersProvider = getService('rolesUsersProvider'); + const kbnClient = getService('kibanaServer'); + const log = getService('log'); + const endpointRegistryHelpers = getService('endpointRegistryHelpers'); + + const roles = Object.values(ROLE); + before(async () => { + if (!endpointRegistryHelpers.isRegistryEnabled()) { + log.warning('These tests are being run with an external package registry'); + } + + const registryUrl = + endpointRegistryHelpers.getRegistryUrlFromTestEnv() ?? getRegistryUrlFromIngest(); + log.info(`Package registry URL for tests: ${registryUrl}`); + try { + await ingestManager.setup(); + } catch (err) { + log.warning(`Error setting up ingestManager: ${err}`); + } + + if (!(await isServerlessKibanaFlavor(kbnClient))) { + // create role/user + for (const role of roles) { + await rolesUsersProvider.createRole({ predefinedRole: role }); + await rolesUsersProvider.createUser({ name: role, roles: [role] }); + } + } + }); + + after(async () => { + if (!(await isServerlessKibanaFlavor(kbnClient))) { + // delete role/user + await rolesUsersProvider.deleteUsers(roles); + await rolesUsersProvider.deleteRoles(roles); + } + }); + + loadTestFile(require.resolve('./datastream_index_creation')); + }); +} From 9d384ef0bda357d8c13320b24599cf45f5339052 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Fri, 25 Oct 2024 15:51:31 -0400 Subject: [PATCH 08/13] Fix bug in test --- .../trial_license_complete_tier/datastream_index_creation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/datastream_index_creation.ts b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/datastream_index_creation.ts index 7b722ec66828..bc029369f3fe 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/datastream_index_creation.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/datastream_index_creation.ts @@ -115,7 +115,7 @@ export default function ({ getService }: FtrProviderContext) { await new Promise(async (resolve, reject) => { try { setTimeout(() => { - resolve(); + resolve(undefined); }, 5000); } catch (error) { reject(error); From 43241e2b435b4f2ca24b5f7f16bfe201af2cf2a7 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Mon, 28 Oct 2024 10:32:56 -0400 Subject: [PATCH 09/13] Remove unused var --- .../test/security_solution_endpoint/services/endpoint_policy.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts b/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts index 5b7fd8b86f28..8f24f116ca87 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts @@ -55,7 +55,6 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC const supertest = getService('supertest'); const log = getService('log'); const retry = getService('retry'); - const kbnClient = getService('kibanaServer'); const logSupertestApiErrorAndThrow = (message: string, error: any): never => { const responseBody = error?.response?.body; From 9f243d2cd15b66bdf55007f65ebc4e2e6afe0390 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Wed, 30 Oct 2024 12:34:57 -0400 Subject: [PATCH 10/13] Fix script fleet services import that was causing a failure in cypress --- .../scripts/endpoint/common/fleet_services.ts | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts index 2f4324be3b4d..da14cf21a6ee 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts @@ -67,7 +67,6 @@ import semver from 'semver'; import axios from 'axios'; import { userInfo } from 'os'; import pRetry from 'p-retry'; -import { AgentPolicyBaseSchema } from '@kbn/fleet-plugin/server/types'; import { getPolicyDataForUpdate } from '../../../common/endpoint/service/policy'; import { fetchActiveSpace } from './spaces'; import { fetchKibanaStatus } from '../../../common/endpoint/utils/kibana_status'; @@ -109,6 +108,42 @@ export const randomAgentPolicyName = (() => { */ const isValidArtifactVersion = (version: string) => !!version.match(/^\d+\.\d+\.\d+(-SNAPSHOT)?$/); +const getAgentPolicyDataForUpdate = ( + agentPolicy: AgentPolicy +): UpdateAgentPolicyRequest['body'] => { + return pick(currentSavedPolicy, [ + 'id', + 'name', + 'namespace', + 'space_ids', + 'description', + 'is_default', + 'is_default_fleet_server', + 'has_fleet_server', + 'is_managed', + 'monitoring_enabled', + 'unenroll_timeout', + 'inactivity_timeout', + 'is_preconfigured', + 'data_output_id', + 'monitoring_output_id', + 'download_source_id', + 'fleet_server_host_id', + 'schema_version', + 'agent_features', + 'is_protected', + 'overrides', + 'advanced_settings', + 'keep_monitoring_alive', + 'supports_agentless', + 'global_data_tags', + 'monitoring_pprof_enabled', + 'monitoring_http', + 'monitoring_diagnostics', + 'uploader', + ]); +}; + export const checkInFleetAgent = async ( esClient: Client, agentId: string, @@ -1452,7 +1487,7 @@ export const updateAgentPolicy = async ( if (patch) { const currentSavedPolicy = await fetchAgentPolicy(kbnClient, id); - fullPolicyData = pick(currentSavedPolicy, Object.keys(AgentPolicyBaseSchema)); + fullPolicyData = getAgentPolicyDataForUpdate(currentSavedPolicy); delete fullPolicyData.id; Object.assign(fullPolicyData, policyData); } From a29b02970f1b060637368d14acb9dcb4ab697fa3 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Wed, 30 Oct 2024 14:22:13 -0400 Subject: [PATCH 11/13] Fix variable --- .../security_solution/scripts/endpoint/common/fleet_services.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts index da14cf21a6ee..c2071690d8d6 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts @@ -111,7 +111,7 @@ const isValidArtifactVersion = (version: string) => !!version.match(/^\d+\.\d+\. const getAgentPolicyDataForUpdate = ( agentPolicy: AgentPolicy ): UpdateAgentPolicyRequest['body'] => { - return pick(currentSavedPolicy, [ + return pick(agentPolicy, [ 'id', 'name', 'namespace', From c885b3baa8f35e8cfdd37d01ff2d6dda09d61254 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Wed, 30 Oct 2024 15:52:31 -0400 Subject: [PATCH 12/13] Fix type --- .../security_solution/scripts/endpoint/common/fleet_services.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts index c2071690d8d6..f627b061e5a5 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts @@ -141,7 +141,7 @@ const getAgentPolicyDataForUpdate = ( 'monitoring_http', 'monitoring_diagnostics', 'uploader', - ]); + ]) as UpdateAgentPolicyRequest['body']; }; export const checkInFleetAgent = async ( From 6f697622b5e35ba8f1a28e2efb4afedf9e51b22a Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Thu, 31 Oct 2024 08:36:12 -0400 Subject: [PATCH 13/13] Fix utility in fleet services scripting lib --- .../scripts/endpoint/common/fleet_services.ts | 39 +++++++++---------- .../trial_license_complete_tier/index.ts | 2 +- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts index f627b061e5a5..a07823194fa6 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts @@ -112,35 +112,32 @@ const getAgentPolicyDataForUpdate = ( agentPolicy: AgentPolicy ): UpdateAgentPolicyRequest['body'] => { return pick(agentPolicy, [ - 'id', - 'name', - 'namespace', - 'space_ids', + 'advanced_settings', + 'agent_features', + 'data_output_id', 'description', + 'download_source_id', + 'fleet_server_host_id', + 'global_data_tags', + 'has_fleet_server', + 'id', + 'inactivity_timeout', 'is_default', 'is_default_fleet_server', - 'has_fleet_server', 'is_managed', + 'is_protected', + 'keep_monitoring_alive', + 'monitoring_diagnostics', 'monitoring_enabled', - 'unenroll_timeout', - 'inactivity_timeout', - 'is_preconfigured', - 'data_output_id', + 'monitoring_http', 'monitoring_output_id', - 'download_source_id', - 'fleet_server_host_id', - 'schema_version', - 'agent_features', - 'is_protected', + 'monitoring_pprof_enabled', + 'name', + 'namespace', 'overrides', - 'advanced_settings', - 'keep_monitoring_alive', + 'space_ids', 'supports_agentless', - 'global_data_tags', - 'monitoring_pprof_enabled', - 'monitoring_http', - 'monitoring_diagnostics', - 'uploader', + 'unenroll_timeout', ]) as UpdateAgentPolicyRequest['body']; }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/index.ts b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/index.ts index 2d96bd3edceb..dba8ed191925 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/policy/trial_license_complete_tier/index.ts @@ -12,7 +12,7 @@ import { ROLE } from '../../../../config/services/security_solution_edr_workflow export default function endpointAPIIntegrationTests(providerContext: FtrProviderContext) { const { loadTestFile, getService } = providerContext; - describe('Endpoint Policv', function () { + describe('Endpoint Policy', function () { const ingestManager = getService('ingestManager'); const rolesUsersProvider = getService('rolesUsersProvider'); const kbnClient = getService('kibanaServer');