[Attack Discovery] Share actionsClient within the rule execution context (#10142) (#216644)

## Summary

Main ticket ([Internal
link](https://github.com/elastic/security-team/issues/12004))

We are working on a new AI Assistant feature which will allow users to
schedule Attack Discovery generation. It will also allow users to setup
actions. The plan is to use alerting framework for that and create a new
rule type with executor handler. One thing which is missing right now is
the `actionsClient` (to get access and use AI connectors) within the
executor context.

With these changes, we expose `actionsClient` within the
`RuleExecutorOptions` for Attack Discovery Schedule rule type.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Ievgen Sorokopud 2025-04-02 20:35:09 +02:00 committed by GitHub
parent 00e776f166
commit 63f010c41f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 28 additions and 4 deletions

View file

@ -60,3 +60,6 @@ export const ELASTIC_AI_ASSISTANT_EVALUATE_URL =
export const DEFEND_INSIGHTS_ID = 'defend-insights';
export const DEFEND_INSIGHTS = `${ELASTIC_AI_ASSISTANT_INTERNAL_URL}/defend_insights`;
export const DEFEND_INSIGHTS_BY_ID = `${DEFEND_INSIGHTS}/{id}`;
// Attack Discovery
export const ATTACK_DISCOVERY_SCHEDULES_ALERT_TYPE_ID = 'attack-discovery' as const;

View file

@ -452,6 +452,7 @@ describe('Ad Hoc Task Runner', () => {
expect(call.executionId).toEqual(UUID);
expect(call.services).toBeTruthy();
expect(call.services.actionsClient).toBeUndefined();
expect(call.services.alertsClient).not.toBe(null);
expect(call.services.alertsClient?.report).toBeTruthy();
expect(call.services.alertsClient?.setAlertData).toBeTruthy();

View file

@ -14,6 +14,7 @@ import { createTaskRunError, TaskErrorSource } from '@kbn/task-manager-plugin/se
import { nanosToMillis } from '@kbn/event-log-plugin/common';
import type { CancellableTask, RunResult } from '@kbn/task-manager-plugin/server/task';
import { TaskPriority } from '@kbn/task-manager-plugin/server/task';
import { ATTACK_DISCOVERY_SCHEDULES_ALERT_TYPE_ID } from '@kbn/elastic-assistant-common';
import type { AdHocRunStatus } from '../../common/constants';
import { adHocRunStatus } from '../../common/constants';
import type {
@ -235,9 +236,13 @@ export class AdHocTaskRunner implements CancellableTask {
ruleTaskTimeout: ruleType.ruleTaskTimeout,
});
const actionsClient = await this.context.actionsPlugin.getActionsClientWithRequest(fakeRequest);
const { error, stackTrace } = await this.ruleTypeRunner.run({
context: ruleTypeRunnerContext,
alertsClient,
actionsClient:
ruleType.id === ATTACK_DISCOVERY_SCHEDULES_ALERT_TYPE_ID ? actionsClient : undefined,
executionId: this.executionId,
executorServices,
rule: {
@ -279,7 +284,7 @@ export class AdHocTaskRunner implements CancellableTask {
ruleLabel,
previousStartedAt: null,
alertingEventLogger: this.alertingEventLogger,
actionsClient: await this.context.actionsPlugin.getActionsClientWithRequest(fakeRequest),
actionsClient,
alertsClient,
priority: TaskPriority.Low,
});

View file

@ -15,6 +15,8 @@ import type { Logger } from '@kbn/core/server';
import type { ConcreteTaskInstance } from '@kbn/task-manager-plugin/server';
import { createTaskRunError, TaskErrorSource } from '@kbn/task-manager-plugin/server';
import { getErrorSource } from '@kbn/task-manager-plugin/server/task_running';
import type { PublicMethodsOf } from '@kbn/utility-types';
import type { ActionsClient } from '@kbn/actions-plugin/server';
import type { IAlertsClient } from '../alerts_client/types';
import { ErrorWithReason } from '../lib';
import { getTimeRange } from '../lib/get_time_range';
@ -81,6 +83,7 @@ interface RunOpts<
> {
context: RuleTypeRunnerContext;
alertsClient: IAlertsClient<AlertData, State, Context, ActionGroupIds, RecoveryActionGroupId>;
actionsClient?: PublicMethodsOf<ActionsClient>;
executionId: string;
executorServices: ExecutorServices & {
getTimeRangeFn?: (
@ -142,6 +145,7 @@ export class RuleTypeRunner<
public async run({
context,
alertsClient,
actionsClient,
executionId,
executorServices,
rule,
@ -216,6 +220,7 @@ export class RuleTypeRunner<
services: {
alertFactory: alertsClient.factory(),
alertsClient: alertsClient.client(),
actionsClient,
getDataViews: executorServices.getDataViews,
getMaintenanceWindowIds: async () => {
if (context.maintenanceWindowsService) {

View file

@ -18,6 +18,7 @@ import {
} from '@kbn/task-manager-plugin/server';
import { nanosToMillis } from '@kbn/event-log-plugin/server';
import { getErrorSource, isUserError } from '@kbn/task-manager-plugin/server/task_running';
import { ATTACK_DISCOVERY_SCHEDULES_ALERT_TYPE_ID } from '@kbn/elastic-assistant-common';
import { ActionScheduler, type RunResult } from './action_scheduler';
import type {
RuleRunnerErrorStackTraceLog,
@ -367,6 +368,8 @@ export class TaskRunner<
ruleTaskTimeout: this.ruleType.ruleTaskTimeout,
});
const actionsClient = await this.context.actionsPlugin.getActionsClientWithRequest(fakeRequest);
const {
state: updatedRuleTypeState,
error,
@ -374,6 +377,8 @@ export class TaskRunner<
} = await this.ruleTypeRunner.run({
context: ruleTypeRunnerContext,
alertsClient,
actionsClient:
this.ruleType.id === ATTACK_DISCOVERY_SCHEDULES_ALERT_TYPE_ID ? actionsClient : undefined,
executionId: this.executionId,
executorServices,
rule,
@ -402,7 +407,7 @@ export class TaskRunner<
ruleLabel,
previousStartedAt: previousStartedAt ? new Date(previousStartedAt) : null,
alertingEventLogger: this.alertingEventLogger,
actionsClient: await this.context.actionsPlugin.getActionsClientWithRequest(fakeRequest),
actionsClient,
alertsClient,
});

View file

@ -26,7 +26,7 @@ import type { PublicMethodsOf } from '@kbn/utility-types';
import type { SharePluginStart } from '@kbn/share-plugin/server';
import type { DefaultAlert, FieldMap } from '@kbn/alerts-as-data-utils';
import type { Alert } from '@kbn/alerts-as-data-utils';
import type { ActionsApiRequestHandlerContext } from '@kbn/actions-plugin/server';
import type { ActionsApiRequestHandlerContext, ActionsClient } from '@kbn/actions-plugin/server';
import type { AlertsHealth, RuleTypeSolution } from '@kbn/alerting-types';
import type { RuleTypeRegistry as OrigruleTypeRegistry } from './rule_type_registry';
import type { AlertingServerSetup, AlertingServerStart } from './plugin';
@ -99,6 +99,10 @@ export interface RuleExecutorServices<
* @deprecated
*/
alertFactory: PublicAlertFactory<State, Context, ActionGroupIds>;
/**
* Only available for Attack Discovery
*/
actionsClient?: PublicMethodsOf<ActionsClient>;
getDataViews: () => Promise<DataViewsContract>;
getMaintenanceWindowIds: () => Promise<string[]>;
getSearchSourceClient: () => Promise<ISearchStartSearchSource>;

View file

@ -76,7 +76,8 @@
"@kbn/core-security-server-mocks",
"@kbn/core-http-server-utils",
"@kbn/response-ops-rule-params",
"@kbn/datemath"
"@kbn/datemath",
"@kbn/elastic-assistant-common"
],
"exclude": [
"target/**/*"