diff --git a/x-pack/plugins/security_solution/server/integration_tests/lib/helpers.ts b/x-pack/plugins/security_solution/server/integration_tests/lib/helpers.ts index 4cf1b69e0873ae..ccc73435636e96 100644 --- a/x-pack/plugins/security_solution/server/integration_tests/lib/helpers.ts +++ b/x-pack/plugins/security_solution/server/integration_tests/lib/helpers.ts @@ -22,8 +22,8 @@ const asyncUnlink = Util.promisify(Fs.unlink); */ export async function eventually( cb: () => Promise, - duration: number = 60000, - interval: number = 1000 + duration: number = 120000, + interval: number = 3000 ) { let elapsed = 0; diff --git a/x-pack/plugins/security_solution/server/integration_tests/telemetry.test.ts b/x-pack/plugins/security_solution/server/integration_tests/telemetry.test.ts index 36284722cbf592..50d2d5e5cd6499 100644 --- a/x-pack/plugins/security_solution/server/integration_tests/telemetry.test.ts +++ b/x-pack/plugins/security_solution/server/integration_tests/telemetry.test.ts @@ -148,8 +148,7 @@ describe('telemetry tasks', () => { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/187719 - describe.skip('detection-rules', () => { + describe('detection-rules', () => { it('should execute when scheduled', async () => { await mockAndScheduleDetectionRulesTask(); @@ -263,7 +262,7 @@ describe('telemetry tasks', () => { // wait until the events are sent to the telemetry server const body = await eventually(async () => { const found = mockedAxiosPost.mock.calls.find(([url]) => { - return url.startsWith(ENDPOINT_STAGING) && url.endsWith('alerts-endpoint'); + return url.startsWith(ENDPOINT_STAGING) && url.endsWith(TelemetryChannel.ENDPOINT_ALERTS); }); expect(found).not.toBeFalsy(); @@ -274,6 +273,25 @@ describe('telemetry tasks', () => { expect(body).not.toBeFalsy(); expect(body.Endpoint).not.toBeFalsy(); }); + + it('should execute get license info', async () => { + await mockAndScheduleEndpointDiagnosticsTask(); + + // wait until the events are sent to the telemetry server + const body = await eventually(async () => { + const found = mockedAxiosPost.mock.calls.find(([url]) => { + return url.startsWith(ENDPOINT_STAGING) && url.endsWith(TelemetryChannel.ENDPOINT_ALERTS); + }); + + expect(found).not.toBeFalsy(); + + return JSON.parse((found ? found[1] : '{}') as string); + }); + + expect(body).not.toBeFalsy(); + expect(body.license).not.toBeFalsy(); + expect(body.license.status).not.toBeFalsy(); + }); }); describe('endpoint-meta-telemetry', () => { @@ -680,8 +698,7 @@ describe('telemetry tasks', () => { expect(body.file).toStrictEqual(alertsDetectionsRequest.file); }); - // Flaky: https://github.com/elastic/kibana/issues/188234 - it.skip('should manage runtime errors searching endpoint metrics', async () => { + it('should manage runtime errors searching endpoint metrics', async () => { const errorMessage = 'Something went wront'; async function* mockedGenerator( diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/async_sender.ts b/x-pack/plugins/security_solution/server/lib/telemetry/async_sender.ts index 07e098b1cc979e..6c2def2abb61d9 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/async_sender.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/async_sender.ts @@ -21,7 +21,7 @@ import { TelemetryChannel, TelemetryCounter } from './types'; import * as collections from './collections_helpers'; import { CachedSubject, retryOnError$ } from './rxjs_helpers'; import { SenderUtils } from './sender_helpers'; -import { newTelemetryLogger } from './helpers'; +import { copyLicenseFields, newTelemetryLogger } from './helpers'; import { type TelemetryLogger } from './telemetry_logger'; export const DEFAULT_QUEUE_CONFIG: QueueConfig = { @@ -291,6 +291,14 @@ export class AsyncTelemetryEventsSender implements IAsyncTelemetryEventsSender { }; } + if (event.channel === TelemetryChannel.ENDPOINT_ALERTS) { + const licenseInfo = this.telemetryReceiver?.getLicenseInfo(); + additional = { + ...additional, + ...(licenseInfo ? { license: copyLicenseFields(licenseInfo) } : {}), + }; + } + event.payload = { ...event.payload, ...additional, 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 ebff5655d99e03..22f85d19c83d86 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts @@ -102,6 +102,8 @@ export interface ITelemetryReceiver { fetchClusterInfo(): Promise; + getLicenseInfo(): Nullable; + fetchLicenseInfo(): Promise>; closePointInTime(pitId: string): Promise; @@ -248,6 +250,7 @@ export class TelemetryReceiver implements ITelemetryReceiver { private getIndexForType?: (type: string) => string; private alertsIndex?: string; private clusterInfo?: ESClusterInfo; + private licenseInfo?: Nullable; private processTreeFetcher?: Fetcher; private packageService?: PackageService; private experimentalFeatures: ExperimentalFeatures | undefined; @@ -280,6 +283,7 @@ export class TelemetryReceiver implements ITelemetryReceiver { this.soClient = core?.savedObjects.createInternalRepository() as unknown as SavedObjectsClientContract; this.clusterInfo = await this.fetchClusterInfo(); + this.licenseInfo = await this.fetchLicenseInfo(); this.experimentalFeatures = endpointContextService?.experimentalFeatures; const elasticsearch = core?.elasticsearch.client as unknown as IScopedClusterClient; this.processTreeFetcher = new Fetcher(elasticsearch); @@ -291,6 +295,10 @@ export class TelemetryReceiver implements ITelemetryReceiver { return this.clusterInfo; } + public getLicenseInfo(): Nullable { + return this.licenseInfo; + } + public getAlertsIndex(): string | undefined { return this.alertsIndex; } diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/tasks/diagnostic.ts b/x-pack/plugins/security_solution/server/lib/telemetry/tasks/diagnostic.ts index 8148a81e8f915f..a6825a7517b4f4 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/tasks/diagnostic.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/tasks/diagnostic.ts @@ -8,11 +8,10 @@ import type { Logger } from '@kbn/core/server'; import { newTelemetryLogger, getPreviousDiagTaskTimestamp } from '../helpers'; import type { ITelemetryEventsSender } from '../sender'; -import type { TelemetryEvent } from '../types'; +import { TelemetryChannel, type TelemetryEvent } from '../types'; import type { ITelemetryReceiver } from '../receiver'; import type { TaskExecutionPeriod } from '../task'; import type { ITaskMetricsService } from '../task_metrics.types'; -import { TELEMETRY_CHANNEL_ENDPOINT_ALERTS } from '../constants'; import { copyAllowlistedFields, filterList } from '../filterlists'; export function createTelemetryDiagnosticsTaskConfig() { @@ -65,7 +64,7 @@ export function createTelemetryDiagnosticsTaskConfig() { log.l('Sending diagnostic alerts', { alerts_count: alerts.length, }); - await sender.sendOnDemand(TELEMETRY_CHANNEL_ENDPOINT_ALERTS, processedAlerts); + sender.sendAsync(TelemetryChannel.ENDPOINT_ALERTS, processedAlerts); } await taskMetricsService.end(trace);