Skip to content

Commit b27e0ed

Browse files
kibanamachinesemd
andauthored
[8.19] [Security Solution][Auto migrations] Implement migration stop/resume UI (#224102) (#224691)
# Backport This will backport the following commits from `main` to `8.19`: - [[Security Solution][Auto migrations] Implement migration stop/resume UI (#224102)](#224102) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Sergi Massaneda","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-06-20T12:48:13Z","message":"[Security Solution][Auto migrations] Implement migration stop/resume UI (#224102)\n\n## Summary\n\nImplement migration task stop/resume functionality in the UI.\n\nThe _stop_ process takes a bit longer than the _resume_, that's because\nwe ensure the aborted langGraph invocation completely settles, and the\nbackground process is terminated, before showing the _resume_ action,\nwhich involves polling for the migration state for a while.\n\n## Screenshots\n\n\n![ready](https://github.com/user-attachments/assets/12a15a79-974d-4ee7-97cd-70d7ce185e89)\n\nStop feature demo: \n\n\nhttps://github.com/user-attachments/assets/37727d0c-c248-45ff-b9c7-220a59c153f6","sha":"31fe87ae061c1f1b8e375b7c942b88d5414b9e95","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Threat Hunting","Team: SecuritySolution","backport:version","v9.1.0","v8.19.0"],"title":"[Security Solution][Auto migrations] Implement migration stop/resume UI","number":224102,"url":"https://github.com/elastic/kibana/pull/224102","mergeCommit":{"message":"[Security Solution][Auto migrations] Implement migration stop/resume UI (#224102)\n\n## Summary\n\nImplement migration task stop/resume functionality in the UI.\n\nThe _stop_ process takes a bit longer than the _resume_, that's because\nwe ensure the aborted langGraph invocation completely settles, and the\nbackground process is terminated, before showing the _resume_ action,\nwhich involves polling for the migration state for a while.\n\n## Screenshots\n\n\n![ready](https://github.com/user-attachments/assets/12a15a79-974d-4ee7-97cd-70d7ce185e89)\n\nStop feature demo: \n\n\nhttps://github.com/user-attachments/assets/37727d0c-c248-45ff-b9c7-220a59c153f6","sha":"31fe87ae061c1f1b8e375b7c942b88d5414b9e95"}},"sourceBranch":"main","suggestedTargetBranches":["8.19"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/224102","number":224102,"mergeCommit":{"message":"[Security Solution][Auto migrations] Implement migration stop/resume UI (#224102)\n\n## Summary\n\nImplement migration task stop/resume functionality in the UI.\n\nThe _stop_ process takes a bit longer than the _resume_, that's because\nwe ensure the aborted langGraph invocation completely settles, and the\nbackground process is terminated, before showing the _resume_ action,\nwhich involves polling for the migration state for a while.\n\n## Screenshots\n\n\n![ready](https://github.com/user-attachments/assets/12a15a79-974d-4ee7-97cd-70d7ce185e89)\n\nStop feature demo: \n\n\nhttps://github.com/user-attachments/assets/37727d0c-c248-45ff-b9c7-220a59c153f6","sha":"31fe87ae061c1f1b8e375b7c942b88d5414b9e95"}},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Sergi Massaneda <[email protected]>
1 parent f219acf commit b27e0ed

File tree

30 files changed

+695
-192
lines changed

30 files changed

+695
-192
lines changed

x-pack/platform/plugins/private/translations/translations/fr-FR.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43371,7 +43371,6 @@
4337143371
"xpack.securitySolution.siemMigrations.rules.panel.result.summary.failed": "Échoué",
4337243372
"xpack.securitySolution.siemMigrations.rules.panel.result.summary.tableColumn.rules": "Règles",
4337343373
"xpack.securitySolution.siemMigrations.rules.panel.result.summary.title": "Résumé de la traduction",
43374-
"xpack.securitySolution.siemMigrations.rules.panel.translate.button": "Lancer la traduction",
4337543374
"xpack.securitySolution.siemMigrations.rules.panel.uploadMacros.button": "Charger",
4337643375
"xpack.securitySolution.siemMigrations.rules.panel.uploadMissingResources": "Chargez les macros et les consultations manquantes.",
4337743376
"xpack.securitySolution.siemMigrations.rules.retryFailedRulesFailDescription": "Échec du re-traitement des règles de migration",

x-pack/platform/plugins/private/translations/translations/ja-JP.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43342,7 +43342,6 @@
4334243342
"xpack.securitySolution.siemMigrations.rules.panel.result.summary.failed": "失敗",
4334343343
"xpack.securitySolution.siemMigrations.rules.panel.result.summary.tableColumn.rules": "ルール",
4334443344
"xpack.securitySolution.siemMigrations.rules.panel.result.summary.title": "変換概要",
43345-
"xpack.securitySolution.siemMigrations.rules.panel.translate.button": "変換を開始",
4334643345
"xpack.securitySolution.siemMigrations.rules.panel.uploadMacros.button": "アップロード",
4334743346
"xpack.securitySolution.siemMigrations.rules.panel.uploadMissingResources": "欠落しているマクロとルックアップをアップロード",
4334843347
"xpack.securitySolution.siemMigrations.rules.retryFailedRulesFailDescription": "移行ルールを再処理できませんでした",

x-pack/platform/plugins/private/translations/translations/zh-CN.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43413,7 +43413,6 @@
4341343413
"xpack.securitySolution.siemMigrations.rules.panel.result.summary.failed": "失败",
4341443414
"xpack.securitySolution.siemMigrations.rules.panel.result.summary.tableColumn.rules": "规则",
4341543415
"xpack.securitySolution.siemMigrations.rules.panel.result.summary.title": "转换摘要",
43416-
"xpack.securitySolution.siemMigrations.rules.panel.translate.button": "开始转换",
4341743416
"xpack.securitySolution.siemMigrations.rules.panel.uploadMacros.button": "上传",
4341843417
"xpack.securitySolution.siemMigrations.rules.panel.uploadMissingResources": "上传缺失的宏和查找。",
4341943418
"xpack.securitySolution.siemMigrations.rules.retryFailedRulesFailDescription": "无法重新处理迁移规则",

x-pack/solutions/security/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,16 @@
66
*/
77

88
import { notificationServiceMock } from '@kbn/core/public/mocks';
9-
10-
import { createTGridMocks } from '@kbn/timelines-plugin/public/mock';
11-
129
import {
1310
createKibanaContextProviderMock,
1411
createUseUiSettingMock,
1512
createUseUiSetting$Mock,
1613
createStartServicesMock,
1714
createWithKibanaMock,
1815
} from '../kibana_react.mock';
19-
import { mockApm } from '../../apm/service.mock';
2016
import { APP_UI_ID } from '../../../../../common/constants';
21-
import { mockCasesContract } from '@kbn/cases-plugin/public/mocks';
17+
18+
export { useKibana } from './use_kibana';
2219

2320
const mockStartServicesMock = createStartServicesMock();
2421
export const KibanaServices = {
@@ -40,49 +37,6 @@ export const KibanaServices = {
4037
getBuildFlavor: jest.fn(() => 'traditional'),
4138
getPrebuiltRulesPackageVersion: jest.fn(() => undefined),
4239
};
43-
export const useKibana = jest.fn().mockReturnValue({
44-
services: {
45-
...mockStartServicesMock,
46-
apm: mockApm(),
47-
uiSettings: {
48-
get: jest.fn(),
49-
set: jest.fn(),
50-
},
51-
cases: mockCasesContract(),
52-
data: {
53-
...mockStartServicesMock.data,
54-
search: {
55-
...mockStartServicesMock.data.search,
56-
search: jest.fn().mockImplementation(() => ({
57-
subscribe: jest.fn().mockImplementation(() => ({
58-
error: jest.fn(),
59-
next: jest.fn(),
60-
unsubscribe: jest.fn(),
61-
})),
62-
})),
63-
},
64-
query: {
65-
...mockStartServicesMock.data.query,
66-
filterManager: {
67-
addFilters: jest.fn(),
68-
getFilters: jest.fn(),
69-
getUpdates$: jest.fn().mockReturnValue({ subscribe: jest.fn() }),
70-
setAppFilters: jest.fn(),
71-
},
72-
},
73-
},
74-
osquery: {
75-
OsqueryResults: jest.fn().mockReturnValue(null),
76-
fetchAllLiveQueries: jest.fn().mockReturnValue({ data: { data: { items: [] } } }),
77-
},
78-
timelines: createTGridMocks(),
79-
savedObjectsTagging: {
80-
ui: {
81-
getTableColumnDefinition: jest.fn(),
82-
},
83-
},
84-
},
85-
});
8640
export const useUiSetting = jest.fn(createUseUiSettingMock());
8741
export const useUiSetting$ = jest.fn(createUseUiSetting$Mock());
8842
export const useHttp = jest.fn().mockReturnValue(createStartServicesMock().http);
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { createTGridMocks } from '@kbn/timelines-plugin/public/mock';
9+
10+
import { createStartServicesMock } from '../kibana_react.mock';
11+
import { mockApm } from '../../apm/service.mock';
12+
import { mockCasesContract } from '@kbn/cases-plugin/public/mocks';
13+
14+
const mockStartServicesMock = createStartServicesMock();
15+
16+
export const useKibana = jest.fn().mockReturnValue({
17+
services: {
18+
...mockStartServicesMock,
19+
apm: mockApm(),
20+
uiSettings: {
21+
get: jest.fn(),
22+
set: jest.fn(),
23+
},
24+
cases: mockCasesContract(),
25+
data: {
26+
...mockStartServicesMock.data,
27+
search: {
28+
...mockStartServicesMock.data.search,
29+
search: jest.fn().mockImplementation(() => ({
30+
subscribe: jest.fn().mockImplementation(() => ({
31+
error: jest.fn(),
32+
next: jest.fn(),
33+
unsubscribe: jest.fn(),
34+
})),
35+
})),
36+
},
37+
query: {
38+
...mockStartServicesMock.data.query,
39+
filterManager: {
40+
addFilters: jest.fn(),
41+
getFilters: jest.fn(),
42+
getUpdates$: jest.fn().mockReturnValue({ subscribe: jest.fn() }),
43+
setAppFilters: jest.fn(),
44+
},
45+
},
46+
},
47+
osquery: {
48+
OsqueryResults: jest.fn().mockReturnValue(null),
49+
fetchAllLiveQueries: jest.fn().mockReturnValue({ data: { data: { items: [] } } }),
50+
},
51+
timelines: createTGridMocks(),
52+
savedObjectsTagging: {
53+
ui: {
54+
getTableColumnDefinition: jest.fn(),
55+
},
56+
},
57+
},
58+
});

x-pack/solutions/security/plugins/security_solution/public/common/lib/kibana/kibana_react.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,11 @@
77

88
import {
99
KibanaContextProvider,
10-
useKibana,
1110
useUiSetting,
1211
useUiSetting$,
1312
withKibana,
1413
} from '@kbn/kibana-react-plugin/public';
1514
import type { ApmBase } from '@elastic/apm-rum';
16-
import type { StartServices } from '../../../types';
1715

18-
const useTypedKibana = () => useKibana<StartServices>();
19-
20-
export {
21-
ApmBase,
22-
KibanaContextProvider,
23-
useTypedKibana as useKibana,
24-
useUiSetting,
25-
useUiSetting$,
26-
withKibana,
27-
};
16+
export { useKibana } from './use_kibana';
17+
export { ApmBase, KibanaContextProvider, useUiSetting, useUiSetting$, withKibana };
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { useKibana as useKibanaGeneric } from '@kbn/kibana-react-plugin/public';
9+
import type { StartServices } from '../../../types';
10+
11+
export const useKibana = useKibanaGeneric<StartServices>;

x-pack/solutions/security/plugins/security_solution/public/common/lib/telemetry/events/siem_migrations/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export const siemMigrationEventNames = {
2323
[SiemMigrationsEventTypes.SetupMacrosQueryCopied]: 'Copy macros query',
2424
[SiemMigrationsEventTypes.SetupLookupNameCopied]: 'Copy lookup name',
2525
[SiemMigrationsEventTypes.StartMigration]: 'Start rule migration',
26+
[SiemMigrationsEventTypes.StopMigration]: 'Stop rule migration',
2627
[SiemMigrationsEventTypes.TranslatedRuleUpdate]: 'Update translated rule',
2728
[SiemMigrationsEventTypes.TranslatedRuleInstall]: 'Install translated rule',
2829
[SiemMigrationsEventTypes.TranslatedRuleBulkInstall]: 'Bulk install translated rules',
@@ -197,6 +198,11 @@ const eventSchemas: SiemMigrationsTelemetryEventSchemas = {
197198
},
198199
},
199200
},
201+
[SiemMigrationsEventTypes.StopMigration]: {
202+
...baseResultActionSchema,
203+
...migrationIdSchema,
204+
...eventNameSchema,
205+
},
200206

201207
// Translated Rule Events
202208

x-pack/solutions/security/plugins/security_solution/public/common/lib/telemetry/events/siem_migrations/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ export enum SiemMigrationsEventTypes {
4343
* When the translation of rules is started
4444
*/
4545
StartMigration = 'siem_migrations_start_rules_migration',
46+
/**
47+
* When the translation of rules is stopped
48+
*/
49+
StopMigration = 'siem_migrations_stop_rules_migration',
4650
/**
4751
* When a translated rule is updated
4852
*/
@@ -112,6 +116,11 @@ export interface ReportStartMigrationActionParams extends BaseResultActionParams
112116
retryFilter?: SiemMigrationRetryFilter;
113117
}
114118

119+
export interface ReportStopMigrationActionParams extends BaseResultActionParams {
120+
eventName: string;
121+
migrationId: string;
122+
}
123+
115124
// Translated rule actions
116125

117126
export interface ReportTranslatedRuleUpdateActionParams {
@@ -149,6 +158,7 @@ export interface SiemMigrationsTelemetryEventsMap {
149158
[SiemMigrationsEventTypes.SetupLookupNameCopied]: ReportSetupLookupNameCopiedActionParams;
150159
[SiemMigrationsEventTypes.SetupResourcesUploaded]: ReportSetupResourcesUploadedActionParams;
151160
[SiemMigrationsEventTypes.StartMigration]: ReportStartMigrationActionParams;
161+
[SiemMigrationsEventTypes.StopMigration]: ReportStopMigrationActionParams;
152162
[SiemMigrationsEventTypes.TranslatedRuleUpdate]: ReportTranslatedRuleUpdateActionParams;
153163
[SiemMigrationsEventTypes.TranslatedRuleInstall]: ReportTranslatedRuleInstallActionParams;
154164
[SiemMigrationsEventTypes.TranslatedRuleBulkInstall]: ReportTranslatedRuleBulkInstallActionParams;

x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/api/index.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
SIEM_RULE_MIGRATION_MISSING_PRIVILEGES_PATH,
2828
SIEM_RULE_MIGRATION_RULES_PATH,
2929
SIEM_RULE_MIGRATIONS_INTEGRATIONS_STATS_PATH,
30+
SIEM_RULE_MIGRATION_STOP_PATH,
3031
} from '../../../../common/siem_migrations/constants';
3132
import type {
3233
CreateRuleMigrationResponse,
@@ -46,6 +47,7 @@ import type {
4647
GetRuleMigrationRulesResponse,
4748
CreateRuleMigrationRulesRequestBody,
4849
GetRuleMigrationIntegrationsStatsResponse,
50+
StopRuleMigrationResponse,
4951
} from '../../../../common/siem_migrations/model/api/rules/rule_migration.gen';
5052

5153
export interface GetRuleMigrationStatsParams {
@@ -189,6 +191,23 @@ export const startRuleMigration = async ({
189191
);
190192
};
191193

194+
export interface StopRuleMigrationParams {
195+
/** `id` of the migration to stop */
196+
migrationId: string;
197+
/** Optional AbortSignal for cancelling request */
198+
signal?: AbortSignal;
199+
}
200+
/** Stops a new migration with the provided rules. */
201+
export const stopRuleMigration = async ({
202+
migrationId,
203+
signal,
204+
}: StopRuleMigrationParams): Promise<StopRuleMigrationResponse> => {
205+
return KibanaServices.get().http.post<StopRuleMigrationResponse>(
206+
replaceParams(SIEM_RULE_MIGRATION_STOP_PATH, { migration_id: migrationId }),
207+
{ version: '1', signal }
208+
);
209+
};
210+
192211
export interface GetMigrationRulesParams {
193212
/** `id` of the migration to get rules documents for */
194213
migrationId: string;

0 commit comments

Comments
 (0)