mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Security solution] Add additional properties to attack discovery telemetry (#182249)
This commit is contained in:
parent
7d97184065
commit
e306074aa9
7 changed files with 106 additions and 11 deletions
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
|
@ -1348,8 +1348,9 @@ x-pack/plugins/cloud_integrations/cloud_full_story/server/config.ts @elastic/kib
|
|||
/x-pack/plugins/security_solution_ess/ @elastic/security-solution
|
||||
/x-pack/plugins/security_solution_serverless/ @elastic/security-solution
|
||||
|
||||
# AI Assistant in Security Solution
|
||||
# GenAI in Security Solution
|
||||
/x-pack/plugins/security_solution/public/assistant @elastic/security-generative-ai
|
||||
/x-pack/plugins/security_solution/public/attack_discovery @elastic/security-generative-ai
|
||||
/x-pack/test/security_solution_cypress/cypress/e2e/ai_assistant @elastic/security-generative-ai
|
||||
|
||||
# Security Solution cross teams ownership
|
||||
|
|
|
@ -30,16 +30,19 @@ interface GenAiConfig {
|
|||
export const getGenAiConfig = (connector: ActionConnector | undefined): GenAiConfig | undefined => {
|
||||
if (!connector?.isPreconfigured) {
|
||||
const config = (connector as ActionConnectorProps<GenAiConfig, unknown>)?.config;
|
||||
if (config?.apiProvider === OpenAiProviderType.AzureAi) {
|
||||
return {
|
||||
...config,
|
||||
defaultModel: getAzureApiVersionParameter(config.apiUrl ?? ''),
|
||||
};
|
||||
}
|
||||
const { apiProvider, apiUrl, defaultModel } = config ?? {};
|
||||
|
||||
return (connector as ActionConnectorProps<GenAiConfig, unknown>)?.config;
|
||||
return {
|
||||
apiProvider,
|
||||
apiUrl,
|
||||
defaultModel:
|
||||
apiProvider === OpenAiProviderType.AzureAi
|
||||
? getAzureApiVersionParameter(apiUrl ?? '')
|
||||
: defaultModel,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
|
||||
return undefined; // the connector is neither available nor editable
|
||||
};
|
||||
|
||||
export const getActionTypeTitle = (actionType: ActionTypeModel): string => {
|
||||
|
|
|
@ -42,10 +42,16 @@ describe('useAttackDiscoveryTelemetry', () => {
|
|||
await result.current.reportAttackDiscoveriesGenerated({
|
||||
actionTypeId: '.gen-ai',
|
||||
model: 'gpt-4',
|
||||
durationMs: 8000,
|
||||
alertsCount: 20,
|
||||
configuredAlertsCount: 30,
|
||||
});
|
||||
expect(reportAttackDiscoveriesGenerated).toHaveBeenCalledWith({
|
||||
actionTypeId: '.gen-ai',
|
||||
model: 'gpt-4',
|
||||
durationMs: 8000,
|
||||
alertsCount: 20,
|
||||
configuredAlertsCount: 30,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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 type { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import type { ActionConnectorProps } from '@kbn/triggers-actions-ui-plugin/public/types';
|
||||
|
||||
// aligns with OpenAiProviderType from '@kbn/stack-connectors-plugin/common/openai/types'
|
||||
enum OpenAiProviderType {
|
||||
OpenAi = 'OpenAI',
|
||||
AzureAi = 'Azure OpenAI',
|
||||
}
|
||||
|
||||
interface GenAiConfig {
|
||||
apiProvider?: OpenAiProviderType;
|
||||
apiUrl?: string;
|
||||
defaultModel?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GenAiConfig for a given ActionConnector. Note that if the connector is preconfigured,
|
||||
* the config will be undefined as the connector is neither available nor editable.
|
||||
*
|
||||
* @param connector
|
||||
*/
|
||||
export const getGenAiConfig = (connector: ActionConnector | undefined): GenAiConfig | undefined => {
|
||||
if (!connector?.isPreconfigured) {
|
||||
const config = (connector as ActionConnectorProps<GenAiConfig, unknown>)?.config;
|
||||
const { apiProvider, apiUrl, defaultModel } = config ?? {};
|
||||
|
||||
return {
|
||||
apiProvider,
|
||||
apiUrl,
|
||||
defaultModel:
|
||||
apiProvider === OpenAiProviderType.AzureAi
|
||||
? getAzureApiVersionParameter(apiUrl ?? '')
|
||||
: defaultModel,
|
||||
};
|
||||
}
|
||||
|
||||
return undefined; // the connector is neither available nor editable
|
||||
};
|
||||
|
||||
const getAzureApiVersionParameter = (url: string): string | undefined => {
|
||||
const urlSearchParams = new URLSearchParams(new URL(url).search);
|
||||
return urlSearchParams.get('api-version') ?? undefined;
|
||||
};
|
|
@ -16,7 +16,7 @@ import {
|
|||
AttackDiscoveryPostResponse,
|
||||
ELASTIC_AI_ASSISTANT_INTERNAL_API_VERSION,
|
||||
} from '@kbn/elastic-assistant-common';
|
||||
import { isEmpty } from 'lodash/fp';
|
||||
import { isEmpty, uniq } from 'lodash/fp';
|
||||
import moment from 'moment';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { useLocalStorage, useSessionStorage } from 'react-use';
|
||||
|
@ -41,6 +41,7 @@ import {
|
|||
} from '../pages/session_storage';
|
||||
import { ERROR_GENERATING_ATTACK_DISCOVERIES } from '../pages/translations';
|
||||
import type { AttackDiscovery, GenerationInterval } from '../types';
|
||||
import { getGenAiConfig } from './helpers';
|
||||
|
||||
const MAX_GENERATION_INTERVALS = 5;
|
||||
|
||||
|
@ -230,7 +231,17 @@ export const useAttackDiscovery = ({
|
|||
setAttackDiscoveries(newAttackDiscoveries);
|
||||
setLastUpdated(newLastUpdated);
|
||||
setConnectorId?.(connectorId);
|
||||
reportAttackDiscoveriesGenerated({ actionTypeId });
|
||||
const connectorConfig = getGenAiConfig(selectedConnector);
|
||||
reportAttackDiscoveriesGenerated({
|
||||
actionTypeId,
|
||||
durationMs,
|
||||
alertsCount: uniq(
|
||||
newAttackDiscoveries.flatMap((attackDiscovery) => attackDiscovery.alertIds)
|
||||
).length,
|
||||
configuredAlertsCount: knowledgeBase.latestAlerts,
|
||||
provider: connectorConfig?.apiProvider,
|
||||
model: connectorConfig?.defaultModel,
|
||||
});
|
||||
} catch (error) {
|
||||
toasts?.addDanger(error, {
|
||||
title: ERROR_GENERATING_ATTACK_DISCOVERIES,
|
||||
|
|
|
@ -18,6 +18,27 @@ export const insightsGeneratedEvent: TelemetryEvent = {
|
|||
optional: false,
|
||||
},
|
||||
},
|
||||
durationMs: {
|
||||
type: 'integer',
|
||||
_meta: {
|
||||
description: 'Duration of request in ms',
|
||||
optional: false,
|
||||
},
|
||||
},
|
||||
alertsCount: {
|
||||
type: 'integer',
|
||||
_meta: {
|
||||
description: 'Number of unique alerts referenced in the attack discoveries',
|
||||
optional: false,
|
||||
},
|
||||
},
|
||||
configuredAlertsCount: {
|
||||
type: 'integer',
|
||||
_meta: {
|
||||
description: 'Number of alerts configured by the user',
|
||||
optional: false,
|
||||
},
|
||||
},
|
||||
model: {
|
||||
type: 'keyword',
|
||||
_meta: {
|
||||
|
|
|
@ -12,6 +12,9 @@ export interface ReportAttackDiscoveriesGeneratedParams {
|
|||
actionTypeId: string;
|
||||
provider?: string;
|
||||
model?: string;
|
||||
durationMs: number;
|
||||
alertsCount: number;
|
||||
configuredAlertsCount: number;
|
||||
}
|
||||
|
||||
export type ReportAttackDiscoveryTelemetryEventParams = ReportAttackDiscoveriesGeneratedParams;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue