Skip to content

Commit

Permalink
create workflow insight from defend insight
Browse files Browse the repository at this point in the history
  • Loading branch information
joeypoon committed Dec 3, 2024
1 parent 35adcbe commit 2a1610e
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,29 @@ import { LLMChain } from 'langchain/chains';
import { OutputFixingParser } from 'langchain/output_parsers';

import type { AssistantTool, AssistantToolParams } from '@kbn/elastic-assistant-plugin/server';
import type { DefendInsightType } from '@kbn/elastic-assistant-common';
import type {
DefendInsight,
DefendInsightType,
DefendInsightsPostRequestBody,
} from '@kbn/elastic-assistant-common';
import type { KibanaRequest } from '@kbn/core/server';

import { requestHasRequiredAnonymizationParams } from '@kbn/elastic-assistant-plugin/server/lib/langchain/helpers';
import { DEFEND_INSIGHTS_TOOL_ID } from '@kbn/elastic-assistant-common';

import { APP_UI_ID } from '../../../../common';
import { securityWorkflowInsightsService } from '../../../endpoint/services';
import { getAnonymizedEvents } from './get_events';
import { getDefendInsightsOutputParser } from './output_parsers';
import { getDefendInsightsPrompt } from './prompts';
import { buildWorkflowInsights } from './workflow_insights_builders';

export const DEFEND_INSIGHTS_TOOL_DESCRIPTION = 'Call this for Elastic Defend insights.';

export interface DefendInsightsToolParams extends AssistantToolParams {
endpointIds: string[];
insightType: DefendInsightType;
request: KibanaRequest<unknown, unknown, DefendInsightsPostRequestBody>;
}

/**
Expand Down Expand Up @@ -55,6 +63,7 @@ export const DEFEND_INSIGHTS_TOOL: AssistantTool = Object.freeze({
llm,
onNewReplacements,
replacements,
request,
} = params as DefendInsightsToolParams;

return new DynamicTool({
Expand Down Expand Up @@ -104,7 +113,13 @@ export const DEFEND_INSIGHTS_TOOL: AssistantTool = Object.freeze({
}),
timeout: langChainTimeout,
});
const insights = result.records;
const insights: DefendInsight[] = result.records;

const workflowInsights = buildWorkflowInsights({
defendInsights: insights,
request,
});
workflowInsights.map(securityWorkflowInsightsService.create);

return JSON.stringify({ eventsContextCount, insights }, null, 2);
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* 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 moment from 'moment';

import { DefendInsight } from '@kbn/elastic-assistant-common';
import { ENDPOINT_ARTIFACT_LISTS } from '@kbn/securitysolution-list-constants';

import type { SecurityWorkflowInsight } from '../../../../../common/endpoint/types/workflow_insights';

import {
ActionType,
Category,
SourceType,
TargetType,
} from '../../../../../common/endpoint/types/workflow_insights';
import { BuildWorkflowInsightParams } from '.';
import { SUPPORTED_HOST_OS_TYPE } from '../../../../../common/endpoint/constants';

export function buildIncompatibleAntivirusWorkflowInsight(
params: BuildWorkflowInsightParams
): SecurityWorkflowInsight[] {
const currentTime = moment();
const { defendInsights, request } = params;
const { insightType, endpointIds, apiConfig } = request.body;
return defendInsights.map((defendInsight: DefendInsight) => {
const filePaths = (defendInsight.events ?? []).map((event) => event.value);
return {
'@timestamp': currentTime,
// TODO add i18n support
message: 'Incompatible antiviruses detected',
category: Category.Endpoint,
type: insightType,
source: {
type: SourceType.LlmConnector,
id: apiConfig.connectorId,
// TODO use actual time range when we add support
data_range_start: currentTime,
data_range_end: currentTime.clone().add(24, 'hours'),
},
target: {
type: TargetType.Endpoint,
ids: endpointIds,
},
action: {
type: ActionType.Refreshed,
timestamp: currentTime,
},
value: defendInsight.group,
remediation: {
exception_list_items: [
{
list_id: ENDPOINT_ARTIFACT_LISTS.blocklists.id,
name: defendInsight.group,
description: 'Suggested by Security Workflow Insights',
entries: [
{
field: 'file.path.caseless',
operator: 'included',
type: 'match_any',
value: filePaths,
},
],
// TODO add per policy support
tags: ['policy:all'],
os_types: [
// TODO pick this based on endpointIds
SUPPORTED_HOST_OS_TYPE[0],
SUPPORTED_HOST_OS_TYPE[1],
SUPPORTED_HOST_OS_TYPE[2],
],
},
],
},
metadata: {
notes: {
llm_model: apiConfig.model ?? '',
},
},
};
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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 { KibanaRequest } from '@kbn/core/server';
import type { DefendInsightsPostRequestBody } from '@kbn/elastic-assistant-common';

import { DefendInsight, DefendInsightType } from '@kbn/elastic-assistant-common';

import type { SecurityWorkflowInsight } from '../../../../../common/endpoint/types/workflow_insights';

import { InvalidDefendInsightTypeError } from '../errors';
import { buildIncompatibleAntivirusWorkflowInsight } from './incompatible_antivirus';

export interface BuildWorkflowInsightParams {
defendInsights: DefendInsight[];
request: KibanaRequest<unknown, unknown, DefendInsightsPostRequestBody>;
}

export function buildWorkflowInsights(
params: BuildWorkflowInsightParams
): SecurityWorkflowInsight[] {
if (params.request.body.insightType == DefendInsightType.Enum.incompatible_antivirus) {
return buildIncompatibleAntivirusWorkflowInsight(params);
}

throw new InvalidDefendInsightTypeError();
}

0 comments on commit 2a1610e

Please sign in to comment.