[Rules migration] Improvements & fixes (#206658)

## Summary

[Internal link](https://github.com/elastic/security-team/issues/10820)
to the feature details

This PR includes next improvements and fixes

### Improvements

1. [PR feedback] Improved filtering:
https://github.com/elastic/kibana/pull/206089#discussion_r1913256593
2. [PR feedback] Use variable instead of massive destructing object:
https://github.com/elastic/kibana/pull/206089#discussion_r1913268303
3. `Upload` missing resources button
4. Show comment as a tooltip within the `Status` column for the failed
rule
![Screenshot 2025-01-15 at 13 34
11](https://github.com/user-attachments/assets/4c25aeab-3193-490b-90eb-ccc4f4ef8a9f)

### Fixes

1. Better error handling
2. Fetch all existing rules (via batches search) instead of 10k limit

> [!NOTE]  
> This feature needs `siemMigrationsEnabled` experimental flag enabled
to work.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Ievgen Sorokopud 2025-01-17 18:23:33 +01:00 committed by GitHub
parent 5ab8a52187
commit bd19bcc005
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 264 additions and 509 deletions

View file

@ -386,8 +386,6 @@ import type {
InstallMigrationRulesRequestParamsInput,
InstallMigrationRulesRequestBodyInput,
InstallMigrationRulesResponse,
InstallTranslatedMigrationRulesRequestParamsInput,
InstallTranslatedMigrationRulesResponse,
StartRuleMigrationRequestParamsInput,
StartRuleMigrationRequestBodyInput,
StartRuleMigrationResponse,
@ -1736,24 +1734,6 @@ finalize it.
})
.catch(catchAxiosErrorFormatAndThrow);
}
/**
* Installs all translated migration rules
*/
async installTranslatedMigrationRules(props: InstallTranslatedMigrationRulesProps) {
this.log.info(`${new Date().toISOString()} Calling API InstallTranslatedMigrationRules`);
return this.kbnClient
.request<InstallTranslatedMigrationRulesResponse>({
path: replaceParams(
'/internal/siem_migrations/rules/{migration_id}/install_translated',
props.params
),
headers: {
[ELASTIC_HTTP_VERSION_HEADER]: '1',
},
method: 'POST',
})
.catch(catchAxiosErrorFormatAndThrow);
}
async internalUploadAssetCriticalityRecords(props: InternalUploadAssetCriticalityRecordsProps) {
this.log.info(`${new Date().toISOString()} Calling API InternalUploadAssetCriticalityRecords`);
return this.kbnClient
@ -2541,9 +2521,6 @@ export interface InstallMigrationRulesProps {
export interface InstallPrepackedTimelinesProps {
body: InstallPrepackedTimelinesRequestBodyInput;
}
export interface InstallTranslatedMigrationRulesProps {
params: InstallTranslatedMigrationRulesRequestParamsInput;
}
export interface InternalUploadAssetCriticalityRecordsProps {
attachment: FormData;
}

View file

@ -22,8 +22,6 @@ export const SIEM_RULE_MIGRATION_TRANSLATION_STATS_PATH =
`${SIEM_RULE_MIGRATION_PATH}/translation_stats` as const;
export const SIEM_RULE_MIGRATION_STOP_PATH = `${SIEM_RULE_MIGRATION_PATH}/stop` as const;
export const SIEM_RULE_MIGRATION_INSTALL_PATH = `${SIEM_RULE_MIGRATION_PATH}/install` as const;
export const SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH =
`${SIEM_RULE_MIGRATION_PATH}/install_translated` as const;
export const SIEM_RULE_MIGRATIONS_PREBUILT_RULES_PATH =
`${SIEM_RULE_MIGRATION_PATH}/prebuilt_rules` as const;
@ -64,16 +62,3 @@ export const DEFAULT_TRANSLATION_FIELDS = {
to: 'now',
interval: '5m',
} as const;
export enum AuthorFilter {
ELASTIC = 'elastic',
CUSTOM = 'custom',
}
export enum StatusFilter {
INSTALLED = 'installed',
TRANSLATED = 'translated',
PARTIALLY_TRANSLATED = 'partially_translated',
UNTRANSLATABLE = 'untranslatable',
FAILED = 'failed',
}

View file

@ -193,7 +193,7 @@ export type InstallMigrationRulesRequestParamsInput = z.input<
export type InstallMigrationRulesRequestBody = z.infer<typeof InstallMigrationRulesRequestBody>;
export const InstallMigrationRulesRequestBody = z.object({
ids: z.array(NonEmptyString),
ids: z.array(NonEmptyString).optional(),
/**
* Indicates whether installed rules should be enabled
*/
@ -206,29 +206,9 @@ export type InstallMigrationRulesRequestBodyInput = z.input<
export type InstallMigrationRulesResponse = z.infer<typeof InstallMigrationRulesResponse>;
export const InstallMigrationRulesResponse = z.object({
/**
* Indicates rules migrations have been installed.
* Indicates the number of successfully installed migration rules.
*/
installed: z.boolean(),
});
export type InstallTranslatedMigrationRulesRequestParams = z.infer<
typeof InstallTranslatedMigrationRulesRequestParams
>;
export const InstallTranslatedMigrationRulesRequestParams = z.object({
migration_id: NonEmptyString,
});
export type InstallTranslatedMigrationRulesRequestParamsInput = z.input<
typeof InstallTranslatedMigrationRulesRequestParams
>;
export type InstallTranslatedMigrationRulesResponse = z.infer<
typeof InstallTranslatedMigrationRulesResponse
>;
export const InstallTranslatedMigrationRulesResponse = z.object({
/**
* Indicates rules migrations have been installed.
*/
installed: z.boolean(),
installed: z.number(),
});
export type StartRuleMigrationRequestParams = z.infer<typeof StartRuleMigrationRequestParams>;

View file

@ -237,8 +237,6 @@ paths:
application/json:
schema:
type: object
required:
- ids
properties:
ids:
type: array
@ -259,37 +257,8 @@ paths:
- installed
properties:
installed:
type: boolean
description: Indicates rules migrations have been installed.
/internal/siem_migrations/rules/{migration_id}/install_translated:
post:
summary: Installs all translated migration rules
operationId: InstallTranslatedMigrationRules
x-codegen-enabled: true
description: Installs all translated migration rules
tags:
- SIEM Rule Migrations
parameters:
- name: migration_id
in: path
required: true
schema:
description: The migration id to install translated rules for
$ref: '../../../../../common/api/model/primitives.schema.yaml#/components/schemas/NonEmptyString'
responses:
200:
description: Indicates rules migrations have been installed correctly.
content:
application/json:
schema:
type: object
required:
- installed
properties:
installed:
type: boolean
description: Indicates rules migrations have been installed.
type: number
description: Indicates the number of successfully installed migration rules.
/internal/siem_migrations/rules/{migration_id}/start:
put:

View file

@ -0,0 +1,21 @@
/*
* 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 { SiemMigrationStatus } from './constants';
export interface RuleMigrationFilters {
status?: SiemMigrationStatus | SiemMigrationStatus[];
ids?: string[];
installed?: boolean;
installable?: boolean;
prebuilt?: boolean;
failed?: boolean;
fullyTranslated?: boolean;
partiallyTranslated?: boolean;
untranslatable?: boolean;
searchTerm?: string;
}

View file

@ -7,6 +7,7 @@
import { replaceParams } from '@kbn/openapi-common/shared';
import type { RuleMigrationFilters } from '../../../../common/siem_migrations/types';
import type { UpdateRuleMigrationData } from '../../../../common/siem_migrations/model/rule_migration.gen';
import type { LangSmithOptions } from '../../../../common/siem_migrations/model/common.gen';
import { KibanaServices } from '../../../common/lib/kibana';
@ -15,7 +16,6 @@ import type { SiemMigrationRetryFilter } from '../../../../common/siem_migration
import {
SIEM_RULE_MIGRATIONS_PATH,
SIEM_RULE_MIGRATIONS_ALL_STATS_PATH,
SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH,
SIEM_RULE_MIGRATION_INSTALL_PATH,
SIEM_RULE_MIGRATION_PATH,
SIEM_RULE_MIGRATION_START_PATH,
@ -32,7 +32,6 @@ import type {
GetAllStatsRuleMigrationResponse,
GetRuleMigrationResponse,
GetRuleMigrationTranslationStatsResponse,
InstallTranslatedMigrationRulesResponse,
InstallMigrationRulesResponse,
StartRuleMigrationRequestBody,
GetRuleMigrationStatsResponse,
@ -176,22 +175,8 @@ export interface GetRuleMigrationParams {
sortField?: string;
/** Optional direction to sort results by */
sortDirection?: 'asc' | 'desc';
/** Optional search term to filter documents */
searchTerm?: string;
/** Optional rules ids to filter documents */
ids?: string[];
/** Optional attribute to retrieve prebuilt migration rules */
isPrebuilt?: boolean;
/** Optional attribute to retrieve installed migration rules */
isInstalled?: boolean;
/** Optional attribute to retrieve fully translated migration rules */
isFullyTranslated?: boolean;
/** Optional attribute to retrieve partially translated migration rules */
isPartiallyTranslated?: boolean;
/** Optional attribute to retrieve untranslated migration rules */
isUntranslatable?: boolean;
/** Optional attribute to retrieve failed migration rules */
isFailed?: boolean;
/** Optional parameter to filter documents */
filters?: RuleMigrationFilters;
/** Optional AbortSignal for cancelling request */
signal?: AbortSignal;
}
@ -202,14 +187,7 @@ export const getRuleMigrations = async ({
perPage,
sortField,
sortDirection,
searchTerm,
ids,
isPrebuilt,
isInstalled,
isFullyTranslated,
isPartiallyTranslated,
isUntranslatable,
isFailed,
filters,
signal,
}: GetRuleMigrationParams): Promise<GetRuleMigrationResponse> => {
return KibanaServices.get().http.get<GetRuleMigrationResponse>(
@ -221,14 +199,14 @@ export const getRuleMigrations = async ({
per_page: perPage,
sort_field: sortField,
sort_direction: sortDirection,
search_term: searchTerm,
ids,
is_prebuilt: isPrebuilt,
is_installed: isInstalled,
is_fully_translated: isFullyTranslated,
is_partially_translated: isPartiallyTranslated,
is_untranslatable: isUntranslatable,
is_failed: isFailed,
search_term: filters?.searchTerm,
ids: filters?.ids,
is_prebuilt: filters?.prebuilt,
is_installed: filters?.installed,
is_fully_translated: filters?.fullyTranslated,
is_partially_translated: filters?.partiallyTranslated,
is_untranslatable: filters?.untranslatable,
is_failed: filters?.failed,
},
signal,
}
@ -258,7 +236,7 @@ export interface InstallRulesParams {
/** `id` of the migration to install rules for */
migrationId: string;
/** The rule ids to install */
ids: string[];
ids?: string[];
/** Optional indicator to enable the installed rule */
enabled?: boolean;
/** Optional AbortSignal for cancelling request */
@ -277,23 +255,6 @@ export const installMigrationRules = async ({
);
};
export interface InstallTranslatedRulesParams {
/** `id` of the migration to install rules for */
migrationId: string;
/** Optional AbortSignal for cancelling request */
signal?: AbortSignal;
}
/** Installs all the translated rules for a specific migration. */
export const installTranslatedMigrationRules = async ({
migrationId,
signal,
}: InstallTranslatedRulesParams): Promise<InstallTranslatedMigrationRulesResponse> => {
return KibanaServices.get().http.post<InstallTranslatedMigrationRulesResponse>(
replaceParams(SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH, { migration_id: migrationId }),
{ version: '1', signal }
);
};
export interface GetRuleMigrationsPrebuiltRulesParams {
/** `id` of the migration to install rules for */
migrationId: string;

View file

@ -101,7 +101,7 @@ export const MigrationRuleDetailsFlyout: React.FC<MigrationRuleDetailsFlyoutProp
const handleTranslationUpdate = useCallback(
async (ruleName: string, ruleQuery: string) => {
if (!ruleMigration || isLoading) {
if (isLoading) {
return;
}
setIsUpdating(true);
@ -139,13 +139,11 @@ export const MigrationRuleDetailsFlyout: React.FC<MigrationRuleDetailsFlyoutProp
name: i18n.TRANSLATION_TAB_LABEL,
content: (
<TabContentPadding>
{ruleMigration && (
<TranslationTab
ruleMigration={ruleMigration}
matchedPrebuiltRule={matchedPrebuiltRule}
onTranslationUpdate={handleTranslationUpdate}
/>
)}
<TranslationTab
ruleMigration={ruleMigration}
matchedPrebuiltRule={matchedPrebuiltRule}
onTranslationUpdate={handleTranslationUpdate}
/>
</TabContentPadding>
),
}),
@ -242,7 +240,7 @@ export const MigrationRuleDetailsFlyout: React.FC<MigrationRuleDetailsFlyoutProp
<EuiTitle size="m">
<h2 id={migrationsRulesFlyoutTitleId}>
{ruleDetailsToOverview?.name ??
ruleMigration?.original_rule.title ??
ruleMigration.original_rule.title ??
i18n.UNKNOWN_MIGRATION_RULE_TITLE}
</h2>
</EuiTitle>

View file

@ -10,10 +10,8 @@ import type { EuiCommentProps } from '@elastic/eui';
import { EuiCommentList, EuiMarkdownFormat, EuiSpacer } from '@elastic/eui';
import moment from 'moment';
import { AssistantAvatar } from '@kbn/ai-assistant-icon';
import {
RuleMigrationStatusEnum,
type RuleMigration,
} from '../../../../../../../common/siem_migrations/model/rule_migration.gen';
import { type RuleMigration } from '../../../../../../../common/siem_migrations/model/rule_migration.gen';
import { RuleTranslationResult } from '../../../../../../../common/siem_migrations/constants';
import * as i18n from './translations';
interface SummaryTabProps {
@ -33,8 +31,8 @@ export const SummaryTab: React.FC<SummaryTabProps> = React.memo(({ ruleMigration
timelineAvatarAriaLabel: i18n.ASSISTANT_USERNAME,
timelineAvatar: <AssistantAvatar name="machine" size="l" color="subdued" />,
event:
ruleMigration.status === RuleMigrationStatusEnum.failed
? i18n.COMMENT_EVENT_FAILED
ruleMigration.translation_result === RuleTranslationResult.UNTRANSLATABLE
? i18n.COMMENT_EVENT_UNTRANSLATABLE
: i18n.COMMENT_EVENT_TRANSLATED,
timestamp,
children: <EuiMarkdownFormat textSize="s">{comment}</EuiMarkdownFormat>,

View file

@ -28,8 +28,8 @@ export const COMMENT_EVENT_TRANSLATED = i18n.translate(
}
);
export const COMMENT_EVENT_FAILED = i18n.translate(
'xpack.securitySolution.siemMigrations.rules.translationDetails.summaryTab.commentEvent.failedLabel',
export const COMMENT_EVENT_UNTRANSLATABLE = i18n.translate(
'xpack.securitySolution.siemMigrations.rules.translationDetails.summaryTab.commentEvent.untranslatableLabel',
{
defaultMessage: 'failed to translate',
}

View file

@ -96,7 +96,7 @@ export const CALLOUT_PARTIALLY_TRANSLATED_RULE_DESCRIPTION = i18n.translate(
'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.partiallyTranslatedRuleCalloutDescription',
{
defaultMessage:
'To save this rule, finish the query and define its severity. If you need help, please contact Elastic support.',
'To save this rule, finish writing the query. If you need help, please contact Elastic support.',
}
);

View file

@ -9,7 +9,7 @@ import React, { useCallback, useMemo, useState } from 'react';
import type { EuiSelectableOption } from '@elastic/eui';
import { EuiFilterButton, EuiPopover, EuiSelectable } from '@elastic/eui';
import type { EuiSelectableOnChangeEvent } from '@elastic/eui/src/components/selectable/selectable';
import { AuthorFilter } from '../../../../../../common/siem_migrations/constants';
import { AuthorFilter } from '../../../types';
import * as i18n from './translations';
const AUTHOR_FILTER_POPOVER_WIDTH = 150;

View file

@ -7,18 +7,10 @@
import React, { useCallback } from 'react';
import { EuiFilterGroup } from '@elastic/eui';
import type {
AuthorFilter,
StatusFilter,
} from '../../../../../../common/siem_migrations/constants';
import type { AuthorFilter, FilterOptions, StatusFilter } from '../../../types';
import { StatusFilterButton } from './status';
import { AuthorFilterButton } from './author';
export interface FilterOptions {
status?: StatusFilter;
author?: AuthorFilter;
}
export interface MigrationRulesFilterProps {
filterOptions?: FilterOptions;
onFilterOptionsChanged: (filterOptions?: FilterOptions) => void;

View file

@ -9,12 +9,10 @@ import React, { useCallback, useState } from 'react';
import type { EuiSelectableOption } from '@elastic/eui';
import { EuiFilterButton, EuiPopover, EuiSelectable } from '@elastic/eui';
import type { EuiSelectableOnChangeEvent } from '@elastic/eui/src/components/selectable/selectable';
import {
RuleTranslationResult,
StatusFilter,
} from '../../../../../../common/siem_migrations/constants';
import * as i18n from './translations';
import { RuleTranslationResult } from '../../../../../../common/siem_migrations/constants';
import { convertTranslationResultIntoText } from '../../../utils/translation_results';
import { StatusFilter } from '../../../types';
import * as i18n from './translations';
const STATUS_FILTER_POPOVER_WIDTH = 250;

View file

@ -1,25 +0,0 @@
/*
* 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 { AuthorFilter, StatusFilter } from '../../../../../common/siem_migrations/constants';
import type { FilterOptions } from './filters';
export const convertFilterOptions = (filterOptions?: FilterOptions) => {
return {
...(filterOptions?.author === AuthorFilter.ELASTIC ? { isPrebuilt: true } : {}),
...(filterOptions?.author === AuthorFilter.CUSTOM ? { isPrebuilt: false } : {}),
...(filterOptions?.status === StatusFilter.FAILED ? { isFailed: true } : {}),
...(filterOptions?.status === StatusFilter.INSTALLED ? { isInstalled: true } : {}),
...(filterOptions?.status === StatusFilter.TRANSLATED
? { isInstalled: false, isFullyTranslated: true }
: {}),
...(filterOptions?.status === StatusFilter.PARTIALLY_TRANSLATED
? { isPartiallyTranslated: true }
: {}),
...(filterOptions?.status === StatusFilter.UNTRANSLATABLE ? { isUntranslatable: true } : {}),
};
};

View file

@ -27,7 +27,6 @@ import { useMigrationRulesTableColumns } from '../../hooks/use_migration_rules_t
import { useMigrationRuleDetailsFlyout } from '../../hooks/use_migration_rule_preview_flyout';
import { useInstallMigrationRules } from '../../logic/use_install_migration_rules';
import { useGetMigrationRules } from '../../logic/use_get_migration_rules';
import { useInstallTranslatedMigrationRules } from '../../logic/use_install_translated_migration_rules';
import { useGetMigrationTranslationStats } from '../../logic/use_get_migration_translation_stats';
import { useGetMigrationPrebuiltRules } from '../../logic/use_get_migration_prebuilt_rules';
import * as logicI18n from '../../logic/translations';
@ -39,9 +38,9 @@ import {
} from '../../../../../common/siem_migrations/constants';
import * as i18n from './translations';
import { useStartMigration } from '../../service/hooks/use_start_migration';
import type { FilterOptions } from './filters';
import type { FilterOptions } from '../../types';
import { MigrationRulesFilter } from './filters';
import { convertFilterOptions } from './helpers';
import { convertFilterOptions } from './utils/filters';
const DEFAULT_PAGE_SIZE = 10;
const DEFAULT_SORT_FIELD = 'translation_result';
@ -100,8 +99,10 @@ export const MigrationRulesTable: React.FC<MigrationRulesTableProps> = React.mem
perPage: pageSize,
sortField,
sortDirection,
searchTerm,
...convertFilterOptions(filterOptions),
filters: {
searchTerm,
...convertFilterOptions(filterOptions),
},
});
const [selectedRuleMigrations, setSelectedRuleMigrations] = useState<RuleMigration[]>([]);
@ -158,13 +159,11 @@ export const MigrationRulesTable: React.FC<MigrationRulesTableProps> = React.mem
}, []);
const { mutateAsync: installMigrationRules } = useInstallMigrationRules(migrationId);
const { mutateAsync: installTranslatedMigrationRules } =
useInstallTranslatedMigrationRules(migrationId);
const { startMigration, isLoading: isRetryLoading } = useStartMigration(refetchData);
const [isTableLoading, setTableLoading] = useState(false);
const installSingleRule = useCallback(
async (migrationRule: RuleMigration, enabled = false) => {
async (migrationRule: RuleMigration, enabled?: boolean) => {
setTableLoading(true);
try {
await installMigrationRules({ ids: [migrationRule.id], enabled });
@ -178,7 +177,7 @@ export const MigrationRulesTable: React.FC<MigrationRulesTableProps> = React.mem
);
const installSelectedRule = useCallback(
async (enabled = false) => {
async (enabled?: boolean) => {
setTableLoading(true);
try {
await installMigrationRules({
@ -196,17 +195,17 @@ export const MigrationRulesTable: React.FC<MigrationRulesTableProps> = React.mem
);
const installTranslatedRules = useCallback(
async (enable?: boolean) => {
async (enabled?: boolean) => {
setTableLoading(true);
try {
await installTranslatedMigrationRules();
await installMigrationRules({ enabled });
} catch (error) {
addError(error, { title: logicI18n.INSTALL_MIGRATION_RULES_FAILURE });
} finally {
setTableLoading(false);
}
},
[addError, installTranslatedMigrationRules]
[addError, installMigrationRules]
);
const reprocessFailedRules = useCallback(async () => {

View file

@ -0,0 +1,34 @@
/*
* 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 { RuleMigrationFilters } from '../../../../../../common/siem_migrations/types';
import type { FilterOptions } from '../../../types';
import { AuthorFilter, StatusFilter } from '../../../types';
const AUTHOR_FILTERS: Record<AuthorFilter, RuleMigrationFilters> = {
[AuthorFilter.ELASTIC]: { prebuilt: true },
[AuthorFilter.CUSTOM]: { prebuilt: false },
};
const STATUS_FILTERS: Record<StatusFilter, RuleMigrationFilters> = {
[StatusFilter.FAILED]: { failed: true },
[StatusFilter.INSTALLED]: { installed: true },
[StatusFilter.TRANSLATED]: { installed: false, fullyTranslated: true },
[StatusFilter.PARTIALLY_TRANSLATED]: { partiallyTranslated: true },
[StatusFilter.UNTRANSLATABLE]: { untranslatable: true },
};
export const convertFilterOptions = (filterOptions?: FilterOptions) => {
const filters: RuleMigrationFilters = {};
if (filterOptions?.author) {
Object.assign(filters, AUTHOR_FILTERS[filterOptions.author]);
}
if (filterOptions?.status) {
Object.assign(filters, STATUS_FILTERS[filterOptions.status]);
}
return filters;
};

View file

@ -49,8 +49,11 @@ export const StatusBadge: React.FC<StatusBadgeProps> = React.memo(
// Failed
if (migrationRule.status === RuleMigrationStatusEnum.failed) {
const tooltipMessage = migrationRule.comments?.length
? migrationRule.comments[0]
: i18n.RULE_STATUS_FAILED;
return (
<EuiToolTip content={i18n.RULE_STATUS_FAILED}>
<EuiToolTip content={tooltipMessage}>
<EuiFlexGroup gutterSize="xs" alignItems="center">
<EuiFlexItem grow={false}>
<EuiIcon type="warningFilled" color="danger" />

View file

@ -28,6 +28,12 @@ export const GET_MIGRATION_TRANSLATION_STATS_FAILURE = i18n.translate(
}
);
export const INSTALL_MIGRATION_RULES_SUCCESS = (succeeded: number) =>
i18n.translate('xpack.securitySolution.siemMigrations.rules.installMigrationRulesSuccess', {
defaultMessage: '{succeeded, plural, one {# rule} other {# rules}} installed successfully.',
values: { succeeded },
});
export const INSTALL_MIGRATION_RULES_FAILURE = i18n.translate(
'xpack.securitySolution.siemMigrations.rules.installMigrationRulesFailDescription',
{

View file

@ -8,6 +8,7 @@
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { replaceParams } from '@kbn/openapi-common/shared';
import { useCallback } from 'react';
import type { RuleMigrationFilters } from '../../../../common/siem_migrations/types';
import { SIEM_RULE_MIGRATION_PATH } from '../../../../common/siem_migrations/constants';
import { useAppToasts } from '../../../common/hooks/use_app_toasts';
import * as i18n from './translations';
@ -20,14 +21,7 @@ export const useGetMigrationRules = (params: {
perPage?: number;
sortField?: string;
sortDirection?: 'asc' | 'desc';
searchTerm?: string;
ids?: string[];
isPrebuilt?: boolean;
isInstalled?: boolean;
isFullyTranslated?: boolean;
isPartiallyTranslated?: boolean;
isUntranslatable?: boolean;
isFailed?: boolean;
filters?: RuleMigrationFilters;
}) => {
const { addError } = useAppToasts();

View file

@ -17,15 +17,18 @@ import { installMigrationRules } from '../api';
export const INSTALL_MIGRATION_RULES_MUTATION_KEY = ['POST', SIEM_RULE_MIGRATION_INSTALL_PATH];
export const useInstallMigrationRules = (migrationId: string) => {
const { addError } = useAppToasts();
const { addError, addSuccess } = useAppToasts();
const invalidateGetRuleMigrations = useInvalidateGetMigrationRules();
const invalidateGetMigrationTranslationStats = useInvalidateGetMigrationTranslationStats();
return useMutation<InstallMigrationRulesResponse, Error, { ids: string[]; enabled: boolean }>(
({ ids, enabled = false }) => installMigrationRules({ migrationId, ids, enabled }),
return useMutation<InstallMigrationRulesResponse, Error, { ids?: string[]; enabled?: boolean }>(
({ ids, enabled }) => installMigrationRules({ migrationId, ids, enabled }),
{
mutationKey: INSTALL_MIGRATION_RULES_MUTATION_KEY,
onSuccess: ({ installed }) => {
addSuccess(i18n.INSTALL_MIGRATION_RULES_SUCCESS(installed));
},
onError: (error) => {
addError(error, { title: i18n.INSTALL_MIGRATION_RULES_FAILURE });
},

View file

@ -1,41 +0,0 @@
/*
* 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 { useMutation } from '@tanstack/react-query';
import type { InstallTranslatedMigrationRulesResponse } from '../../../../common/siem_migrations/model/api/rules/rule_migration.gen';
import { SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH } from '../../../../common/siem_migrations/constants';
import { useAppToasts } from '../../../common/hooks/use_app_toasts';
import * as i18n from './translations';
import { useInvalidateGetMigrationRules } from './use_get_migration_rules';
import { useInvalidateGetMigrationTranslationStats } from './use_get_migration_translation_stats';
import { installTranslatedMigrationRules } from '../api';
export const INSTALL_ALL_MIGRATION_RULES_MUTATION_KEY = [
'POST',
SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH,
];
export const useInstallTranslatedMigrationRules = (migrationId: string) => {
const { addError } = useAppToasts();
const invalidateGetRuleMigrations = useInvalidateGetMigrationRules();
const invalidateGetMigrationTranslationStats = useInvalidateGetMigrationTranslationStats();
return useMutation<InstallTranslatedMigrationRulesResponse, Error>(
() => installTranslatedMigrationRules({ migrationId }),
{
mutationKey: INSTALL_ALL_MIGRATION_RULES_MUTATION_KEY,
onError: (error) => {
addError(error, { title: i18n.INSTALL_MIGRATION_RULES_FAILURE });
},
onSettled: () => {
invalidateGetRuleMigrations(migrationId);
invalidateGetMigrationTranslationStats(migrationId);
},
}
);
};

View file

@ -7,7 +7,7 @@
import React, { useCallback, useEffect, useMemo } from 'react';
import { EuiSkeletonLoading, EuiSkeletonText, EuiSkeletonTitle } from '@elastic/eui';
import { EuiSkeletonLoading, EuiSkeletonText, EuiSkeletonTitle, EuiSpacer } from '@elastic/eui';
import type { RouteComponentProps } from 'react-router-dom';
import type { RelatedIntegration } from '../../../../common/api/detection_engine';
import { SiemMigrationTaskStatus } from '../../../../common/siem_migrations/constants';
@ -29,6 +29,7 @@ import { useInvalidateGetMigrationRules } from '../logic/use_get_migration_rules
import { useInvalidateGetMigrationTranslationStats } from '../logic/use_get_migration_translation_stats';
import { useGetIntegrations } from '../service/hooks/use_get_integrations';
import { PageTitle } from './page_title';
import { RuleMigrationsUploadMissingPanel } from '../components/migration_status_panels/upload_missing_panel';
type MigrationRulesPageProps = RouteComponentProps<{ migrationId?: string }>;
@ -99,19 +100,24 @@ export const MigrationRulesPage: React.FC<MigrationRulesPageProps> = React.memo(
if (!migrationId || !migrationStats) {
return <UnknownMigration />;
}
if (migrationStats.status === SiemMigrationTaskStatus.FINISHED) {
return (
<MigrationRulesTable
migrationId={migrationId}
refetchData={refetchData}
integrations={integrations}
isIntegrationsLoading={isIntegrationsLoading}
/>
);
}
return (
<RuleMigrationDataInputWrapper onFlyoutClosed={refetchData}>
<>
{migrationStats.status === SiemMigrationTaskStatus.FINISHED && (
<>
<RuleMigrationsUploadMissingPanel
migrationStats={migrationStats}
topSpacerSize="s"
/>
<EuiSpacer size="m" />
<MigrationRulesTable
migrationId={migrationId}
refetchData={refetchData}
integrations={integrations}
isIntegrationsLoading={isIntegrationsLoading}
/>
</>
)}
{migrationStats.status === SiemMigrationTaskStatus.READY && (
<MigrationReadyPanel migrationStats={migrationStats} />
)}

View file

@ -13,3 +13,21 @@ export interface RuleMigrationStats extends RuleMigrationTaskStats {
/** The sequential number of the migration */
number: number;
}
export enum AuthorFilter {
ELASTIC = 'elastic',
CUSTOM = 'custom',
}
export enum StatusFilter {
INSTALLED = 'installed',
TRANSLATED = 'translated',
PARTIALLY_TRANSLATED = 'partially_translated',
UNTRANSLATABLE = 'untranslatable',
FAILED = 'failed',
}
export interface FilterOptions {
status?: StatusFilter;
author?: AuthorFilter;
}

View file

@ -1,10 +0,0 @@
/*
* 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.
*/
export const MAX_CUSTOM_RULES_TO_CREATE_IN_PARALLEL = 50;
export const MAX_PREBUILT_RULES_TO_FETCH = 10_000 as const;
export const MAX_TRANSLATED_RULES_TO_INSTALL = 10_000 as const;

View file

@ -18,7 +18,6 @@ import { registerSiemRuleMigrationsStatsAllRoute } from './stats_all';
import { registerSiemRuleMigrationsResourceUpsertRoute } from './resources/upsert';
import { registerSiemRuleMigrationsResourceGetRoute } from './resources/get';
import { registerSiemRuleMigrationsInstallRoute } from './install';
import { registerSiemRuleMigrationsInstallTranslatedRoute } from './install_translated';
import { registerSiemRuleMigrationsResourceGetMissingRoute } from './resources/missing';
import { registerSiemRuleMigrationsPrebuiltRulesRoute } from './get_prebuilt_rules';
import { registerSiemRuleMigrationsIntegrationsRoute } from './get_integrations';
@ -37,7 +36,6 @@ export const registerSiemRuleMigrationsRoutes = (
registerSiemRuleMigrationsTranslationStatsRoute(router, logger);
registerSiemRuleMigrationsStopRoute(router, logger);
registerSiemRuleMigrationsInstallRoute(router, logger);
registerSiemRuleMigrationsInstallTranslatedRoute(router, logger);
registerSiemRuleMigrationsIntegrationsRoute(router, logger);
registerSiemRuleMigrationsResourceUpsertRoute(router, logger);

View file

@ -49,17 +49,16 @@ export const registerSiemRuleMigrationsInstallRoute = (
const savedObjectsClient = ctx.core.savedObjects.client;
const rulesClient = await ctx.alerting.getRulesClient();
await installTranslated({
const installed = await installTranslated({
migrationId,
ids,
enabled,
securitySolutionContext,
savedObjectsClient,
rulesClient,
logger,
});
return res.ok({ body: { installed: true } });
return res.ok({ body: { installed } });
} catch (err) {
logger.error(err);
return res.badRequest({ body: err.message });

View file

@ -1,68 +0,0 @@
/*
* 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 { IKibanaResponse, Logger } from '@kbn/core/server';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
import { SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH } from '../../../../../common/siem_migrations/constants';
import type { InstallTranslatedMigrationRulesResponse } from '../../../../../common/siem_migrations/model/api/rules/rule_migration.gen';
import { InstallTranslatedMigrationRulesRequestParams } from '../../../../../common/siem_migrations/model/api/rules/rule_migration.gen';
import type { SecuritySolutionPluginRouter } from '../../../../types';
import { withLicense } from './util/with_license';
import { installTranslated } from './util/installation';
export const registerSiemRuleMigrationsInstallTranslatedRoute = (
router: SecuritySolutionPluginRouter,
logger: Logger
) => {
router.versioned
.post({
path: SIEM_RULE_MIGRATION_INSTALL_TRANSLATED_PATH,
access: 'internal',
security: { authz: { requiredPrivileges: ['securitySolution'] } },
})
.addVersion(
{
version: '1',
validate: {
request: {
params: buildRouteValidationWithZod(InstallTranslatedMigrationRulesRequestParams),
},
},
},
withLicense(
async (
context,
req,
res
): Promise<IKibanaResponse<InstallTranslatedMigrationRulesResponse>> => {
const { migration_id: migrationId } = req.params;
try {
const ctx = await context.resolve(['core', 'alerting', 'securitySolution']);
const securitySolutionContext = ctx.securitySolution;
const savedObjectsClient = ctx.core.savedObjects.client;
const rulesClient = await ctx.alerting.getRulesClient();
await installTranslated({
migrationId,
enabled: false,
securitySolutionContext,
savedObjectsClient,
rulesClient,
logger,
});
return res.ok({ body: { installed: true } });
} catch (err) {
logger.error(err);
return res.badRequest({ body: err.message });
}
}
)
);
};

View file

@ -5,8 +5,9 @@
* 2.0.
*/
import type { Logger, SavedObjectsClientContract } from '@kbn/core/server';
import type { SavedObjectsClientContract } from '@kbn/core/server';
import type { RulesClient } from '@kbn/alerting-plugin/server';
import { getErrorMessage } from '../../../../../utils/error_helpers';
import type { UpdateRuleMigrationData } from '../../../../../../common/siem_migrations/model/rule_migration.gen';
import { initPromisePool } from '../../../../../utils/promise_pool';
import type { SecuritySolutionApiRequestHandlerContext } from '../../../../..';
@ -16,15 +17,13 @@ import type { IDetectionRulesClient } from '../../../../detection_engine/rule_ma
import type { RuleResponse } from '../../../../../../common/api/detection_engine';
import type { StoredRuleMigration } from '../../types';
import { getPrebuiltRules, getUniquePrebuiltRuleIds } from './prebuilt_rules';
import {
MAX_CUSTOM_RULES_TO_CREATE_IN_PARALLEL,
MAX_TRANSLATED_RULES_TO_INSTALL,
} from '../constants';
import {
convertMigrationCustomRuleToSecurityRulePayload,
isMigrationCustomRule,
} from '../../../../../../common/siem_migrations/rules/utils';
const MAX_CUSTOM_RULES_TO_CREATE_IN_PARALLEL = 50;
const installPrebuiltRules = async (
rulesToInstall: StoredRuleMigration[],
enabled: boolean,
@ -32,7 +31,7 @@ const installPrebuiltRules = async (
rulesClient: RulesClient,
savedObjectsClient: SavedObjectsClientContract,
detectionRulesClient: IDetectionRulesClient
): Promise<UpdateRuleMigrationData[]> => {
): Promise<{ rulesToUpdate: UpdateRuleMigrationData[]; errors: Error[] }> => {
// Get required prebuilt rules
const prebuiltRulesIds = getUniquePrebuiltRuleIds(rulesToInstall);
const prebuiltRules = await getPrebuiltRules(rulesClient, savedObjectsClient, prebuiltRulesIds);
@ -52,13 +51,16 @@ const installPrebuiltRules = async (
}
);
const errors: Error[] = [];
// Install prebuilt rules
// TODO: we need to do an error handling which can happen during the rule installation
const { results: newlyInstalledRules } = await createPrebuiltRules(
detectionRulesClient,
installable
const { results: newlyInstalledRules, errors: installPrebuiltRulesErrors } =
await createPrebuiltRules(detectionRulesClient, installable);
errors.push(
...installPrebuiltRulesErrors.map(
(err) => new Error(`Error installing prebuilt rule: ${getErrorMessage(err)}`)
)
);
await performTimelinesInstallation(securitySolutionContext);
const installedRules = [
...alreadyInstalledRules,
@ -81,15 +83,18 @@ const installPrebuiltRules = async (
);
});
return rulesToUpdate;
return { rulesToUpdate, errors };
};
export const installCustomRules = async (
rulesToInstall: StoredRuleMigration[],
enabled: boolean,
detectionRulesClient: IDetectionRulesClient,
logger: Logger
): Promise<UpdateRuleMigrationData[]> => {
detectionRulesClient: IDetectionRulesClient
): Promise<{
rulesToUpdate: UpdateRuleMigrationData[];
errors: Error[];
}> => {
const errors: Error[] = [];
const rulesToUpdate: UpdateRuleMigrationData[] = [];
const createCustomRulesOutcome = await initPromisePool({
concurrency: MAX_CUSTOM_RULES_TO_CREATE_IN_PARALLEL,
@ -113,15 +118,12 @@ export const installCustomRules = async (
});
},
});
if (createCustomRulesOutcome.errors) {
// TODO: we need to do an error handling which can happen during the rule creation
logger.debug(
`Failed to create some of the rules because of errors: ${JSON.stringify(
createCustomRulesOutcome.errors
)}`
);
}
return rulesToUpdate;
errors.push(
...createCustomRulesOutcome.errors.map(
(err) => new Error(`Error installing custom rule: ${getErrorMessage(err)}`)
)
);
return { rulesToUpdate, errors };
};
interface InstallTranslatedProps {
@ -155,11 +157,6 @@ interface InstallTranslatedProps {
* The saved objects client
*/
savedObjectsClient: SavedObjectsClientContract;
/**
* The logger
*/
logger: Logger;
}
export const installTranslated = async ({
@ -169,51 +166,63 @@ export const installTranslated = async ({
securitySolutionContext,
rulesClient,
savedObjectsClient,
logger,
}: InstallTranslatedProps) => {
}: InstallTranslatedProps): Promise<number> => {
const detectionRulesClient = securitySolutionContext.getDetectionRulesClient();
const ruleMigrationsClient = securitySolutionContext.getSiemRuleMigrationsClient();
const { data: rulesToInstall } = await ruleMigrationsClient.data.rules.get(migrationId, {
filters: { ids, installable: true },
from: 0,
size: MAX_TRANSLATED_RULES_TO_INSTALL,
let installedCount = 0;
const installationErrors: Error[] = [];
// Install rules that matched Elastic prebuilt rules
const prebuiltRuleBatches = ruleMigrationsClient.data.rules.searchBatches(migrationId, {
filters: { ids, installable: true, prebuilt: true },
});
const { customRulesToInstall, prebuiltRulesToInstall } = rulesToInstall.reduce(
(acc, item) => {
if (item.elastic_rule?.prebuilt_rule_id) {
acc.prebuiltRulesToInstall.push(item);
} else {
acc.customRulesToInstall.push(item);
}
return acc;
},
{ customRulesToInstall: [], prebuiltRulesToInstall: [] } as {
customRulesToInstall: StoredRuleMigration[];
prebuiltRulesToInstall: StoredRuleMigration[];
}
);
const updatedPrebuiltRules = await installPrebuiltRules(
prebuiltRulesToInstall,
enabled,
securitySolutionContext,
rulesClient,
savedObjectsClient,
detectionRulesClient
);
const updatedCustomRules = await installCustomRules(
customRulesToInstall,
enabled,
detectionRulesClient,
logger
);
const rulesToUpdate: UpdateRuleMigrationData[] = [...updatedPrebuiltRules, ...updatedCustomRules];
if (rulesToUpdate.length) {
let prebuiltRulesToInstall = await prebuiltRuleBatches.next();
while (prebuiltRulesToInstall.length) {
const { rulesToUpdate, errors } = await installPrebuiltRules(
prebuiltRulesToInstall,
enabled,
securitySolutionContext,
rulesClient,
savedObjectsClient,
detectionRulesClient
);
installedCount += rulesToUpdate.length;
installationErrors.push(...errors);
await ruleMigrationsClient.data.rules.update(rulesToUpdate);
prebuiltRulesToInstall = await prebuiltRuleBatches.next();
}
let installTimelinesError: string | undefined;
if (installedCount > 0) {
const { error } = await performTimelinesInstallation(securitySolutionContext);
installTimelinesError = error;
}
// Install rules with custom translation
const customRuleBatches = ruleMigrationsClient.data.rules.searchBatches(migrationId, {
filters: { ids, installable: true, prebuilt: false },
});
let customRulesToInstall = await customRuleBatches.next();
while (customRulesToInstall.length) {
const { rulesToUpdate, errors } = await installCustomRules(
customRulesToInstall,
enabled,
detectionRulesClient
);
installedCount += rulesToUpdate.length;
installationErrors.push(...errors);
await ruleMigrationsClient.data.rules.update(rulesToUpdate);
customRulesToInstall = await customRuleBatches.next();
}
// Throw an error if needed
if (installTimelinesError) {
throw new Error(`Error installing prepackaged timelines: ${installTimelinesError}`);
}
if (installationErrors.length) {
throw new Error(installationErrors.map((err) => err.message).join());
}
return installedCount;
};

View file

@ -6,7 +6,7 @@
*/
import type { RuleMigrationRetryFilter } from '../../../../../../common/siem_migrations/model/rule_migration.gen';
import type { RuleMigrationFilters } from '../../data/rule_migrations_data_rules_client';
import type { RuleMigrationFilters } from '../../../../../../common/siem_migrations/types';
const RETRY_FILTERS: Record<RuleMigrationRetryFilter, RuleMigrationFilters> = {
failed: { failed: true },

View file

@ -15,6 +15,7 @@ import type {
QueryDslQueryContainer,
Duration,
} from '@elastic/elasticsearch/lib/api/types';
import type { RuleMigrationFilters } from '../../../../../common/siem_migrations/types';
import type { InternalUpdateRuleMigrationData, StoredRuleMigration } from '../types';
import {
SiemMigrationStatus,
@ -36,18 +37,6 @@ export type CreateRuleMigrationInput = Omit<
export type RuleMigrationDataStats = Omit<RuleMigrationTaskStats, 'status'>;
export type RuleMigrationAllDataStats = RuleMigrationDataStats[];
export interface RuleMigrationFilters {
status?: SiemMigrationStatus | SiemMigrationStatus[];
ids?: string[];
installed?: boolean;
installable?: boolean;
prebuilt?: boolean;
failed?: boolean;
fullyTranslated?: boolean;
partiallyTranslated?: boolean;
untranslatable?: boolean;
searchTerm?: string;
}
export interface RuleMigrationGetOptions {
filters?: RuleMigrationFilters;
sort?: RuleMigrationSort;
@ -397,66 +386,55 @@ export class RuleMigrationsDataRulesClient extends RuleMigrationsDataBaseClient
private getFilterQuery(
migrationId: string,
{
status,
ids,
installed,
installable,
prebuilt,
searchTerm,
failed,
fullyTranslated,
partiallyTranslated,
untranslatable,
}: RuleMigrationFilters = {}
filters: RuleMigrationFilters = {}
): QueryDslQueryContainer {
const filter: QueryDslQueryContainer[] = [{ term: { migration_id: migrationId } }];
if (status) {
if (Array.isArray(status)) {
filter.push({ terms: { status } });
if (filters.status) {
if (Array.isArray(filters.status)) {
filter.push({ terms: { status: filters.status } });
} else {
filter.push({ term: { status } });
filter.push({ term: { status: filters.status } });
}
}
if (ids) {
filter.push({ terms: { _id: ids } });
if (filters.ids) {
filter.push({ terms: { _id: filters.ids } });
}
if (searchTerm?.length) {
filter.push(searchConditions.matchTitle(searchTerm));
if (filters.searchTerm?.length) {
filter.push(searchConditions.matchTitle(filters.searchTerm));
}
if (installed === true) {
if (filters.installed === true) {
filter.push(searchConditions.isInstalled());
} else if (installed === false) {
} else if (filters.installed === false) {
filter.push(searchConditions.isNotInstalled());
}
if (installable === true) {
if (filters.installable === true) {
filter.push(...searchConditions.isInstallable());
} else if (installable === false) {
} else if (filters.installable === false) {
filter.push(...searchConditions.isNotInstallable());
}
if (prebuilt === true) {
if (filters.prebuilt === true) {
filter.push(searchConditions.isPrebuilt());
} else if (prebuilt === false) {
} else if (filters.prebuilt === false) {
filter.push(searchConditions.isCustom());
}
if (failed === true) {
if (filters.failed === true) {
filter.push(searchConditions.isFailed());
} else if (failed === false) {
} else if (filters.failed === false) {
filter.push(searchConditions.isNotFailed());
}
if (fullyTranslated === true) {
if (filters.fullyTranslated === true) {
filter.push(searchConditions.isFullyTranslated());
} else if (fullyTranslated === false) {
} else if (filters.fullyTranslated === false) {
filter.push(searchConditions.isNotFullyTranslated());
}
if (partiallyTranslated === true) {
if (filters.partiallyTranslated === true) {
filter.push(searchConditions.isPartiallyTranslated());
} else if (partiallyTranslated === false) {
} else if (filters.partiallyTranslated === false) {
filter.push(searchConditions.isNotPartiallyTranslated());
}
if (untranslatable === true) {
if (filters.untranslatable === true) {
filter.push(searchConditions.isUntranslatable());
} else if (untranslatable === false) {
} else if (filters.untranslatable === false) {
filter.push(searchConditions.isNotUntranslatable());
}
return { bool: { filter } };

View file

@ -8,16 +8,14 @@
import type { AuthenticatedUser, Logger } from '@kbn/core/server';
import { AbortError, abortSignalToPromise } from '@kbn/kibana-utils-plugin/server';
import type { RunnableConfig } from '@langchain/core/runnables';
import type { RuleMigrationFilters } from '../../../../../common/siem_migrations/types';
import {
SiemMigrationStatus,
SiemMigrationTaskStatus,
} from '../../../../../common/siem_migrations/constants';
import type { RuleMigrationTaskStats } from '../../../../../common/siem_migrations/model/rule_migration.gen';
import type { RuleMigrationsDataClient } from '../data/rule_migrations_data_client';
import type {
RuleMigrationDataStats,
RuleMigrationFilters,
} from '../data/rule_migrations_data_rules_client';
import type { RuleMigrationDataStats } from '../data/rule_migrations_data_rules_client';
import type { SiemRuleMigrationsClientDependencies } from '../types';
import { getRuleMigrationAgent } from './agent';
import type { MigrateRuleState } from './agent/types';

View file

@ -123,7 +123,6 @@ import {
InstallMigrationRulesRequestBodyInput,
} from '@kbn/security-solution-plugin/common/siem_migrations/model/api/rules/rule_migration.gen';
import { InstallPrepackedTimelinesRequestBodyInput } from '@kbn/security-solution-plugin/common/api/timeline/install_prepackaged_timelines/install_prepackaged_timelines_route.gen';
import { InstallTranslatedMigrationRulesRequestParamsInput } from '@kbn/security-solution-plugin/common/siem_migrations/model/api/rules/rule_migration.gen';
import { ListEntitiesRequestQueryInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/entity_store/entities/list_entities.gen';
import { PatchRuleRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/crud/patch_rule/patch_rule_route.gen';
import { PatchTimelineRequestBodyInput } from '@kbn/security-solution-plugin/common/api/timeline/patch_timelines/patch_timeline_route.gen';
@ -1208,27 +1207,6 @@ finalize it.
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send(props.body as object);
},
/**
* Installs all translated migration rules
*/
installTranslatedMigrationRules(
props: InstallTranslatedMigrationRulesProps,
kibanaSpace: string = 'default'
) {
return supertest
.post(
routeWithNamespace(
replaceParams(
'/internal/siem_migrations/rules/{migration_id}/install_translated',
props.params
),
kibanaSpace
)
)
.set('kbn-xsrf', 'true')
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
},
internalUploadAssetCriticalityRecords(kibanaSpace: string = 'default') {
return supertest
.post(routeWithNamespace('/internal/asset_criticality/upload_csv', kibanaSpace))
@ -1860,9 +1838,6 @@ export interface InstallMigrationRulesProps {
export interface InstallPrepackedTimelinesProps {
body: InstallPrepackedTimelinesRequestBodyInput;
}
export interface InstallTranslatedMigrationRulesProps {
params: InstallTranslatedMigrationRulesRequestParamsInput;
}
export interface ListEntitiesProps {
query: ListEntitiesRequestQueryInput;
}