Skip to content

Commit

Permalink
[8.17] [8.x] [Telemetry][Security Solution] Index metadata collector (#…
Browse files Browse the repository at this point in the history
…194004) (#204311) (#204628)

# Backport

This will backport the following commits from `8.x` to `8.17`:
- [[8.x] [Telemetry][Security Solution] Index metadata collector
(#194004) (#204311)](#204311)

<!--- Backport version: 8.9.8 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Sebastián
Zaffarano","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-12-16T16:05:02Z","message":"[8.x]
[Telemetry][Security Solution] Index metadata collector (#194004)
(#204311)\n\n# Backport\n\nThis will backport the following commits from
`main` to `8.x`:\n- [[Telemetry][Security Solution] Index metadata
collector\n(#194004)](https://github.com/elastic/kibana/pull/194004)\n\n<!---
Backport version: 8.9.8 -->\n\n### Questions ?\nPlease refer to the
[Backport
tool\ndocumentation](https://github.com/sqren/backport)\n\n<!--BACKPORT
[{\"author\":{\"name\":\"Sebastián\nZaffarano\",\"email\":\"[email protected]\"},\"sourceCommit\":{\"committedDate\":\"2024-12-13T18:31:03Z\",\"message\":\"[Telemetry][Security\nSolution]
Index metadata collector
(#194004)\\n\\n##\nSummary\\r\\n\\r\\nImplements a security_solution
task scheduled to run once\na day to\\r\\ncollect the following
information:\\r\\n\\r\\n1. Datastreams\nstats\\r\\n2. Indices
stats\\r\\n3. ILMs stats\\r\\n4. ILM configs\\r\\n\\r\\nThe\ntask allows
a runtime configuration to limit the number of\nindices\\r\\nand data
streams to analyze or event to disable the
feature\nentirely.\\r\\n\\r\\nOnce the data is gathered, the task sends
it as EBT\nevents.\\r\\n\\r\\n---------\\r\\n\\r\\nCo-authored-by:
kibanamachine\n<[email protected]>\\r\\nCo-authored-by:\nElastic
Machine\n<[email protected]>\",\"sha\":\"36b344a4c58a3d78a892288e0eef71e9ff163b9d\",\"branchLabelMapping\":{\"^v9.0.0$\":\"main\",\"^v8.18.0$\":\"8.x\",\"^v(\\\\d+).(\\\\d+).\\\\d+$\":\"$1.$2\"}},\"sourcePullRequest\":{\"labels\":[\"release_note:skip\",\"v9.0.0\",\"Team:\nSecuritySolution\",\"backport:all-open\",\"ci:cloud-deploy\"],\"number\":194004,\"url\":\"https://github.com/elastic/kibana/pull/194004\",\"mergeCommit\":{\"message\":\"[Telemetry][Security\nSolution]
Index metadata collector
(#194004)\\n\\n##\nSummary\\r\\n\\r\\nImplements a security_solution
task scheduled to run once\na day to\\r\\ncollect the following
information:\\r\\n\\r\\n1. Datastreams\nstats\\r\\n2. Indices
stats\\r\\n3. ILMs stats\\r\\n4. ILM configs\\r\\n\\r\\nThe\ntask allows
a runtime configuration to limit the number of\nindices\\r\\nand data
streams to analyze or event to disable the
feature\nentirely.\\r\\n\\r\\nOnce the data is gathered, the task sends
it as EBT\nevents.\\r\\n\\r\\n---------\\r\\n\\r\\nCo-authored-by:
kibanamachine\n<[email protected]>\\r\\nCo-authored-by:\nElastic
Machine\n<[email protected]>\",\"sha\":\"36b344a4c58a3d78a892288e0eef71e9ff163b9d\"}},\"sourceBranch\":\"main\",\"suggestedTargetBranches\":[],\"targetPullRequestStates\":[{\"branch\":\"main\",\"label\":\"v9.0.0\",\"labelRegex\":\"^v9.0.0$\",\"isSourceBranch\":true,\"state\":\"MERGED\",\"url\":\"https://github.com/elastic/kibana/pull/194004\",\"number\":194004,\"mergeCommit\":{\"message\":\"[Telemetry][Security\nSolution]
Index metadata collector
(#194004)\\n\\n##\nSummary\\r\\n\\r\\nImplements a security_solution
task scheduled to run once\na day to\\r\\ncollect the following
information:\\r\\n\\r\\n1. Datastreams\nstats\\r\\n2. Indices
stats\\r\\n3. ILMs stats\\r\\n4. ILM configs\\r\\n\\r\\nThe\ntask allows
a runtime configuration to limit the number of\nindices\\r\\nand data
streams to analyze or event to disable the
feature\nentirely.\\r\\n\\r\\nOnce the data is gathered, the task sends
it as EBT\nevents.\\r\\n\\r\\n---------\\r\\n\\r\\nCo-authored-by:
kibanamachine\n<[email protected]>\\r\\nCo-authored-by:\nElastic
Machine\n<[email protected]>\",\"sha\":\"36b344a4c58a3d78a892288e0eef71e9ff163b9d\"}}]}]\nBACKPORT-->\n\nCo-authored-by:
Elastic Machine
<[email protected]>","sha":"7a3de72bbe94a87bd972602b29212764f2619951","branchLabelMapping":{"^v8.16.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["backport"],"number":204311,"url":"https://github.com/elastic/kibana/pull/204311","mergeCommit":{"message":"[8.x]
[Telemetry][Security Solution] Index metadata collector (#194004)
(#204311)\n\n# Backport\n\nThis will backport the following commits from
`main` to `8.x`:\n- [[Telemetry][Security Solution] Index metadata
collector\n(#194004)](https://github.com/elastic/kibana/pull/194004)\n\n<!---
Backport version: 8.9.8 -->\n\n### Questions ?\nPlease refer to the
[Backport
tool\ndocumentation](https://github.com/sqren/backport)\n\n<!--BACKPORT
[{\"author\":{\"name\":\"Sebastián\nZaffarano\",\"email\":\"[email protected]\"},\"sourceCommit\":{\"committedDate\":\"2024-12-13T18:31:03Z\",\"message\":\"[Telemetry][Security\nSolution]
Index metadata collector
(#194004)\\n\\n##\nSummary\\r\\n\\r\\nImplements a security_solution
task scheduled to run once\na day to\\r\\ncollect the following
information:\\r\\n\\r\\n1. Datastreams\nstats\\r\\n2. Indices
stats\\r\\n3. ILMs stats\\r\\n4. ILM configs\\r\\n\\r\\nThe\ntask allows
a runtime configuration to limit the number of\nindices\\r\\nand data
streams to analyze or event to disable the
feature\nentirely.\\r\\n\\r\\nOnce the data is gathered, the task sends
it as EBT\nevents.\\r\\n\\r\\n---------\\r\\n\\r\\nCo-authored-by:
kibanamachine\n<[email protected]>\\r\\nCo-authored-by:\nElastic
Machine\n<[email protected]>\",\"sha\":\"36b344a4c58a3d78a892288e0eef71e9ff163b9d\",\"branchLabelMapping\":{\"^v9.0.0$\":\"main\",\"^v8.18.0$\":\"8.x\",\"^v(\\\\d+).(\\\\d+).\\\\d+$\":\"$1.$2\"}},\"sourcePullRequest\":{\"labels\":[\"release_note:skip\",\"v9.0.0\",\"Team:\nSecuritySolution\",\"backport:all-open\",\"ci:cloud-deploy\"],\"number\":194004,\"url\":\"https://github.com/elastic/kibana/pull/194004\",\"mergeCommit\":{\"message\":\"[Telemetry][Security\nSolution]
Index metadata collector
(#194004)\\n\\n##\nSummary\\r\\n\\r\\nImplements a security_solution
task scheduled to run once\na day to\\r\\ncollect the following
information:\\r\\n\\r\\n1. Datastreams\nstats\\r\\n2. Indices
stats\\r\\n3. ILMs stats\\r\\n4. ILM configs\\r\\n\\r\\nThe\ntask allows
a runtime configuration to limit the number of\nindices\\r\\nand data
streams to analyze or event to disable the
feature\nentirely.\\r\\n\\r\\nOnce the data is gathered, the task sends
it as EBT\nevents.\\r\\n\\r\\n---------\\r\\n\\r\\nCo-authored-by:
kibanamachine\n<[email protected]>\\r\\nCo-authored-by:\nElastic
Machine\n<[email protected]>\",\"sha\":\"36b344a4c58a3d78a892288e0eef71e9ff163b9d\"}},\"sourceBranch\":\"main\",\"suggestedTargetBranches\":[],\"targetPullRequestStates\":[{\"branch\":\"main\",\"label\":\"v9.0.0\",\"labelRegex\":\"^v9.0.0$\",\"isSourceBranch\":true,\"state\":\"MERGED\",\"url\":\"https://github.com/elastic/kibana/pull/194004\",\"number\":194004,\"mergeCommit\":{\"message\":\"[Telemetry][Security\nSolution]
Index metadata collector
(#194004)\\n\\n##\nSummary\\r\\n\\r\\nImplements a security_solution
task scheduled to run once\na day to\\r\\ncollect the following
information:\\r\\n\\r\\n1. Datastreams\nstats\\r\\n2. Indices
stats\\r\\n3. ILMs stats\\r\\n4. ILM configs\\r\\n\\r\\nThe\ntask allows
a runtime configuration to limit the number of\nindices\\r\\nand data
streams to analyze or event to disable the
feature\nentirely.\\r\\n\\r\\nOnce the data is gathered, the task sends
it as EBT\nevents.\\r\\n\\r\\n---------\\r\\n\\r\\nCo-authored-by:
kibanamachine\n<[email protected]>\\r\\nCo-authored-by:\nElastic
Machine\n<[email protected]>\",\"sha\":\"36b344a4c58a3d78a892288e0eef71e9ff163b9d\"}}]}]\nBACKPORT-->\n\nCo-authored-by:
Elastic Machine
<[email protected]>","sha":"7a3de72bbe94a87bd972602b29212764f2619951"}},"sourceBranch":"8.x","suggestedTargetBranches":[],"targetPullRequestStates":[]}]
BACKPORT-->

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
szaffarano and elasticmachine authored Jan 9, 2025
1 parent 6dd7925 commit 81fd45e
Show file tree
Hide file tree
Showing 43 changed files with 3,100 additions and 136 deletions.
1 change: 1 addition & 0 deletions .buildkite/ftr_security_serverless_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ disabled:
- x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/configs/serverless.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/basic_license_essentials_tier/configs/serverless.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/telemetry/trial_license_complete_tier/configs/serverless.config.ts
- x-pack/test/security_solution_api_integration/test_suites/telemetry/configs/serverless.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/user_roles/trial_license_complete_tier/configs/serverless.config.ts
- x-pack/test/security_solution_api_integration/test_suites/genai/nlp_cleanup_task/trial_license_complete_tier/configs/serverless.config.ts
- x-pack/test/security_solution_api_integration/test_suites/genai/nlp_cleanup_task/basic_license_essentials_tier/configs/serverless.config.ts
Expand Down
1 change: 1 addition & 0 deletions .buildkite/ftr_security_stateful_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ enabled:
- x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/configs/ess.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/basic_license_essentials_tier/configs/ess.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/telemetry/trial_license_complete_tier/configs/ess.config.ts
- x-pack/test/security_solution_api_integration/test_suites/telemetry/configs/ess.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/user_roles/trial_license_complete_tier/configs/ess.config.ts
- x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/configs/ess.config.ts
- x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/basic_license_essentials_tier/configs/ess.config.ts
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* 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 Path from 'path';
import axios from 'axios';

import { cloneDeep } from 'lodash';

import { telemetryConfiguration } from '../lib/telemetry/configuration';
import {
TaskManagerPlugin,
type TaskManagerStartContract,
} from '@kbn/task-manager-plugin/server/plugin';

import {
setupTestServers,
removeFile,
mockAxiosPost,
DEFAULT_GET_ROUTES,
mockAxiosGet,
getRandomInt,
} from './lib/helpers';

import {
type TestElasticsearchUtils,
type TestKibanaUtils,
} from '@kbn/core-test-helpers-kbn-server';
import { Plugin as SecuritySolutionPlugin } from '../plugin';
import { getTelemetryTasks, runSoonConfigTask } from './lib/telemetry_helpers';
import type { SecurityTelemetryTask } from '../lib/telemetry/task';

jest.mock('axios');

const logFilePath = Path.join(__dirname, 'config.logs.log');
const taskManagerStartSpy = jest.spyOn(TaskManagerPlugin.prototype, 'start');
const securitySolutionStartSpy = jest.spyOn(SecuritySolutionPlugin.prototype, 'start');

const mockedAxiosGet = jest.spyOn(axios, 'get');
const mockedAxiosPost = jest.spyOn(axios, 'post');

const securitySolutionPlugin = jest.spyOn(SecuritySolutionPlugin.prototype, 'start');

describe('configuration', () => {
let esServer: TestElasticsearchUtils;
let kibanaServer: TestKibanaUtils;
let taskManagerPlugin: TaskManagerStartContract;
let tasks: SecurityTelemetryTask[];

beforeAll(async () => {
await removeFile(logFilePath);

const servers = await setupTestServers(logFilePath);

esServer = servers.esServer;
kibanaServer = servers.kibanaServer;

expect(taskManagerStartSpy).toHaveBeenCalledTimes(1);
taskManagerPlugin = taskManagerStartSpy.mock.results[0].value;

expect(securitySolutionStartSpy).toHaveBeenCalledTimes(1);

tasks = getTelemetryTasks(securitySolutionStartSpy);

expect(securitySolutionPlugin).toHaveBeenCalledTimes(1);
});

afterAll(async () => {
if (kibanaServer) {
await kibanaServer.stop();
}
if (esServer) {
await esServer.stop();
}
});

beforeEach(async () => {
jest.clearAllMocks();
mockAxiosPost(mockedAxiosPost);
});

afterEach(async () => {});

describe('configuration task', () => {
it('should keep default values when no new config was provided', async () => {
const before = cloneDeep(telemetryConfiguration);

await runSoonConfigTask(tasks, taskManagerPlugin);

expect(telemetryConfiguration).toEqual(before);
});

it('should update values with new manifest', async () => {
const expected = {
telemetry_max_buffer_size: getRandomInt(1, 100),
max_security_list_telemetry_batch: getRandomInt(1, 100),
max_endpoint_telemetry_batch: getRandomInt(1, 100),
max_detection_rule_telemetry_batch: getRandomInt(1, 100),
max_detection_alerts_batch: getRandomInt(1, 100),
use_async_sender: true,
pagination_config: {
max_page_size_bytes: getRandomInt(1, 100),
num_docs_to_sample: getRandomInt(1, 100),
},
sender_channels: {
default: {
buffer_time_span_millis: getRandomInt(1, 100),
inflight_events_threshold: getRandomInt(1, 100),
max_payload_size_bytes: getRandomInt(1, 100),
},
},
indices_metadata_config: {
indices_threshold: getRandomInt(1, 100),
datastreams_threshold: getRandomInt(1, 100),
max_prefixes: getRandomInt(1, 100),
max_group_size: getRandomInt(1, 100),
},
};

mockAxiosGet(mockedAxiosGet, [
...DEFAULT_GET_ROUTES,
[/.*telemetry-buffer-and-batch-sizes-v1.*/, { status: 200, data: cloneDeep(expected) }],
]);

await runSoonConfigTask(tasks, taskManagerPlugin);

expect(telemetryConfiguration.telemetry_max_buffer_size).toEqual(
expected.telemetry_max_buffer_size
);
expect(telemetryConfiguration.max_security_list_telemetry_batch).toEqual(
expected.max_security_list_telemetry_batch
);
expect(telemetryConfiguration.max_endpoint_telemetry_batch).toEqual(
expected.max_endpoint_telemetry_batch
);
expect(telemetryConfiguration.max_detection_rule_telemetry_batch).toEqual(
expected.max_detection_rule_telemetry_batch
);
expect(telemetryConfiguration.max_detection_alerts_batch).toEqual(
expected.max_detection_alerts_batch
);
expect(telemetryConfiguration.use_async_sender).toEqual(expected.use_async_sender);
expect(telemetryConfiguration.sender_channels).toEqual(expected.sender_channels);
expect(telemetryConfiguration.pagination_config).toEqual(expected.pagination_config);
expect(telemetryConfiguration.indices_metadata_config).toEqual(
expected.indices_metadata_config
);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ import Util from 'util';
import type { ElasticsearchClient } from '@kbn/core/server';
import deepmerge from 'deepmerge';
import { createTestServers, createRootWithCorePlugins } from '@kbn/core-test-helpers-kbn-server';

export const DEFAULT_GET_ROUTES: Array<[RegExp, unknown]> = [
[new RegExp('.*/ping$'), { status: 200 }],
[
/.*kibana\/manifest\/artifacts.*/,
{
status: 200,
data: 'x-pack/plugins/security_solution/server/lib/telemetry/__mocks__/kibana-artifacts.zip',
},
],
];

export const DEFAULT_POST_ROUTES: Array<[RegExp, unknown]> = [[/.*/, { status: 200 }]];

const asyncUnlink = Util.promisify(Fs.unlink);

/**
Expand Down Expand Up @@ -127,3 +141,35 @@ export function updateTimestamps(data: object[]): object[] {
return { ...d, '@timestamp': new Date(currentTimeMillis + (i + 1) * 100) };
});
}

export function mockAxiosPost(
postSpy: jest.SpyInstance,
routes: Array<[RegExp, unknown]> = DEFAULT_POST_ROUTES
) {
postSpy.mockImplementation(async (url: string) => {
for (const [route, returnValue] of routes) {
if (route.test(url)) {
return returnValue;
}
}
return { status: 404 };
});
}

export function mockAxiosGet(
getSpy: jest.SpyInstance,
routes: Array<[RegExp, unknown]> = DEFAULT_GET_ROUTES
) {
getSpy.mockImplementation(async (url: string) => {
for (const [route, returnValue] of routes) {
if (route.test(url)) {
return returnValue;
}
}
return { status: 404 };
});
}

export function getRandomInt(min: number, max: number): number {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ import {
deleteExceptionListItem,
} from '@kbn/lists-plugin/server/services/exception_lists';
import { LEGACY_AGENT_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common/constants';
import type { TaskManagerStartContract } from '@kbn/task-manager-plugin/server';

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 { bulkInsert, updateTimestamps } from './helpers';
import { bulkInsert, eventually, updateTimestamps } from './helpers';
import { TelemetryEventsSender } from '../../lib/telemetry/sender';
import type {
SecuritySolutionPluginStart,
Expand Down Expand Up @@ -397,3 +398,24 @@ export function getTelemetryTaskType(task: SecurityTelemetryTask): string {
return '';
}
}

export async function runSoonConfigTask(
tasks: SecurityTelemetryTask[],
taskManagerPlugin: TaskManagerStartContract
) {
const configTaskType = 'security:telemetry-configuration';
const configTask = getTelemetryTask(tasks, configTaskType);
const runAfter = new Date();
await eventually(async () => {
await taskManagerPlugin.runSoon(configTask.getTaskId());
});

// wait until the task finishes
await eventually(async () => {
const hasRun = await taskManagerPlugin
.get(configTask.getTaskId())
.then((t) => new Date(t.state.lastExecutionTimestamp) > runAfter)
.catch(() => false);
expect(hasRun).toBe(true);
});
}
Loading

0 comments on commit 81fd45e

Please sign in to comment.