[8.17] [Telemetry][Security Solution] Send new Endpoint field (#209149) (#209503)

# Backport

This will backport the following commits from `main` to `8.17`:
- [[Telemetry][Security Solution] Send new Endpoint field
(#209149)](https://github.com/elastic/kibana/pull/209149)

<!--- Backport version: 9.4.3 -->

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

<!--BACKPORT [{"author":{"name":"Sebastián
Zaffarano","email":"sebastian.zaffarano@elastic.co"},"sourceCommit":{"committedDate":"2025-02-04T10:49:25Z","message":"[Telemetry][Security
Solution] Send new Endpoint field (#209149)\n\n## Summary\r\n\r\nMake
the Security Solution `endpoint-meta-telemetry` task send the
new\r\nEndpoint field `Endpoint.metrics.top_process_trees`\r\n\r\n###
Checklist\r\n\r\nCheck the PR satisfies following conditions.
\r\n\r\nReviewers should verify this PR satisfies this list as
well.\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"e15d089b369462cbd9d777a24dcd15582b7cba10","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:
SecuritySolution","backport:prev-major","v8.18.0","v9.1.0","v8.19.0"],"title":"[Telemetry][Security
Solution] Send new Endpoint
field","number":209149,"url":"https://github.com/elastic/kibana/pull/209149","mergeCommit":{"message":"[Telemetry][Security
Solution] Send new Endpoint field (#209149)\n\n## Summary\r\n\r\nMake
the Security Solution `endpoint-meta-telemetry` task send the
new\r\nEndpoint field `Endpoint.metrics.top_process_trees`\r\n\r\n###
Checklist\r\n\r\nCheck the PR satisfies following conditions.
\r\n\r\nReviewers should verify this PR satisfies this list as
well.\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"e15d089b369462cbd9d777a24dcd15582b7cba10"}},"sourceBranch":"main","suggestedTargetBranches":["8.18","8.x"],"targetPullRequestStates":[{"branch":"8.18","label":"v8.18.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/209149","number":209149,"mergeCommit":{"message":"[Telemetry][Security
Solution] Send new Endpoint field (#209149)\n\n## Summary\r\n\r\nMake
the Security Solution `endpoint-meta-telemetry` task send the
new\r\nEndpoint field `Endpoint.metrics.top_process_trees`\r\n\r\n###
Checklist\r\n\r\nCheck the PR satisfies following conditions.
\r\n\r\nReviewers should verify this PR satisfies this list as
well.\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"e15d089b369462cbd9d777a24dcd15582b7cba10"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Sebastián Zaffarano <sebastian.zaffarano@elastic.co>
This commit is contained in:
Kibana Machine 2025-02-04 23:52:35 +11:00 committed by GitHub
parent 01eecf8a45
commit c16c8f6900
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 5276 additions and 7 deletions

View file

@ -167,11 +167,14 @@ export class PreviewTelemetryEventsSender implements ITelemetryEventsSender {
}
public sendAsync(channel: TelemetryChannel, events: unknown[]): void {
this.composite.sendAsync(channel, events);
const result = this.composite.simulateSendAsync(channel, events);
this.sentMessages = [...this.sentMessages, ...result];
}
public simulateSendAsync(channel: TelemetryChannel, events: unknown[]): string[] {
return this.composite.simulateSendAsync(channel, events);
const result = this.composite.simulateSendAsync(channel, events);
this.sentMessages = [...this.sentMessages, ...result];
return result;
}
public updateQueueConfig(channel: TelemetryChannel, config: QueueConfig): void {

View file

@ -34,19 +34,18 @@ export class PreviewTaskMetricsService implements ITaskMetricsService {
}
public start(name: string): Trace {
this.logger.error('Simulating TaskMetricsService.start');
this.logger.info('Simulating TaskMetricsService.start');
return this.composite.start(name);
}
public createTaskMetric(trace: Trace, error?: Error): TaskMetric {
this.logger.error('Simulating TaskMetricsService.createTaskMetric');
this.logger.info('Simulating TaskMetricsService.createTaskMetric');
return this.composite.createTaskMetric(trace, error);
}
public async end(trace: Trace, error?: Error): Promise<void> {
this.logger.error('Simulating TaskMetricsService.end');
this.logger.info('Simulating TaskMetricsService.end');
const metric = this.composite.createTaskMetric(trace, error);
const result = this.sender.simulateSendAsync(TelemetryChannel.TASK_METRICS, [metric]);
this.sentMessages = [...this.sentMessages, ...result];
this.sender.simulateSendAsync(TelemetryChannel.TASK_METRICS, [metric]);
}
}

View file

@ -312,6 +312,7 @@ class EndpointMetadataProcessor {
system_impact: systemImpact,
threads,
event_filter: eventFilter,
top_process_trees: topProcessTrees,
} = endpointMetric.Endpoint.metrics;
const endpointPolicyDetail = extractEndpointPolicyConfig(policyConfig);
if (endpointPolicyDetail) {
@ -336,6 +337,7 @@ class EndpointMetadataProcessor {
systemImpact,
threads,
eventFilter,
topProcessTrees,
},
endpoint_meta: {
os: endpointMetric.host.os,

View file

@ -281,6 +281,22 @@ export interface EndpointMetrics {
active_global_count: number;
active_user_count: number;
};
top_process_trees: {
values: Event[];
};
}
interface Event {
event_count: number;
last_seen: string;
sample: Sample;
}
interface Sample {
command_line: string;
entity_id: string;
executable: string;
parent_command_line: string;
}
interface EndpointMetricOS {

View file

@ -0,0 +1,69 @@
{
"type": "data_stream",
"value": {
"data_stream": "metrics-endpoint.metrics-01",
"template": {
"_meta": {
"managed": true,
"managed_by": "fleet",
"package": {
"name": "endpoint"
}
},
"data_stream": {
"allow_custom_routing": false,
"hidden": false
},
"ignore_missing_component_templates": [],
"index_patterns": [
"metrics-endpoint.metrics-*"
],
"name": "metrics-endpoint.metrics",
"priority": 200,
"template": {
"mappings": {
"_meta": {
"managed": true,
"managed_by": "fleet",
"package": {
"name": "endpoint"
}
},
"date_detection": false,
"dynamic_templates": [],
"properties": {
"@timestamp": {
"type": "date"
},
"agent": {
"properties": {
"id": {
"type": "keyword"
}
}
},
"Endpoint": {
"properties": {
"metrics": {
"properties": {
"threads": {
"properties": {
"cpu": {
"properties": {
"mean": {
"type": "float"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}

View file

@ -9,5 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context';
export default ({ loadTestFile }: FtrProviderContext): void => {
describe('Security Solution - Telemetry', function () {
loadTestFile(require.resolve('./tasks/indices_metadata'));
loadTestFile(require.resolve('./tasks/endpoint'));
});
};

View file

@ -0,0 +1,106 @@
/*
* 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 { FtrProviderContext } from '../../../ftr_provider_context';
import { getSecurityTelemetryStats } from '../../detections_response/utils';
export default ({ getService }: FtrProviderContext) => {
const logger = getService('log');
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const es = getService('es');
describe('Endpoint metrics and info task.', function () {
describe('@ess @serverless Execution', () => {
this.tags('skipServerless');
beforeEach(async () => {
await esArchiver
.load('x-pack/test/security_solution_api_integration/es_archive/endpoint/metrics', {
useCreate: true,
})
.catch((e) => {
logger.error('>> Endpoint metrics and info task: load');
logger.error(e);
});
await es
.updateByQuery({
index: '.ds-metrics-endpoint.metrics-*',
script: {
source:
'ctx._source["@timestamp"] = Instant.ofEpochMilli(System.currentTimeMillis()).toString();',
},
})
.catch((e) => {
logger.error('>> Endpoint metrics and info task: update timestamps');
logger.error(e);
});
});
afterEach(async () => {
await esArchiver
.unload('x-pack/test/security_solution_api_integration/es_archive/endpoint/metrics')
.catch((e) => {
logger.error('>> Endpoint metrics and info task: unload');
logger.error(e);
});
});
it('should execute when scheduled', async () => {
const endpoints = await getSecurityTelemetryStats(supertest, logger).then((stats) => {
return stats.endpoints as any[];
});
expect(endpoints).to.not.be(undefined);
expect(endpoints).to.length(4);
});
it('should execute send mandatory fields', async () => {
const endpoints = await getSecurityTelemetryStats(supertest, logger).then((stats) => {
return stats.endpoints as any[];
});
expect(endpoints).to.not.be(undefined);
expect(endpoints).to.length(4);
const metrics = endpoints.flat().filter((endpoint) => {
return endpoint.endpoint_metrics !== undefined;
});
expect(metrics).to.length(3);
for (const metric of metrics) {
expect(metric.endpoint_metrics.cpu).to.not.be(undefined);
expect(metric.endpoint_metrics.memory).to.not.be(undefined);
expect(metric.endpoint_metrics.uptime).to.not.be(undefined);
expect(metric.endpoint_metrics.documentsVolume).to.not.be(undefined);
expect(metric.endpoint_metrics.maliciousBehaviorRules).to.not.be(undefined);
expect(metric.endpoint_metrics.systemImpact).to.not.be(undefined);
expect(metric.endpoint_metrics.threads).to.not.be(undefined);
expect(metric.endpoint_metrics.eventFilter).to.not.be(undefined);
}
const topProcessTrees = metrics
.filter((metric) => {
return metric.endpoint_metrics.topProcessTrees !== undefined;
})
.map((metric) => {
return metric.endpoint_metrics.topProcessTrees;
});
expect(topProcessTrees).to.length(1);
const topProcessTree = topProcessTrees[0];
expect(topProcessTree.values).to.length(3);
const event = topProcessTree.values[0];
expect(event.event_count).to.be(1726);
expect(event.last_seen).to.be('2025-01-28T16:43:49.0Z');
expect(event.sample.command_line).to.match(/.*python.*/);
expect(event.sample.entity_id).to.be('CaOqGgCnYo6Wxqe5CYLRBQ');
expect(event.sample.executable).to.be('python3.10');
expect(event.sample.parent_command_line).to.be('-bash');
});
});
});
};