mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Security Solution] Move rule actions field and its validation into the common folder (#215494)
## Summary With this PR we make `RuleActionsField` component and relevant validations reusable outside of and not bound to the rules management. As part of the Attack Discovery Scheduling [feature](https://github.com/elastic/security-team/issues/10142) we would like to be able to setup schedules (similar to detection rules, just named differently within the feature space) and be able to add actions (email, slack, webhook etc.). Currently `RuleActionsField` lives inside the `x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation/components/` folder. We could just reference it from within the Attack Discovery folder, but for better code structure it will be good to put it into a common place. ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [x] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/8075 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
637c61aedd
commit
760b0cfca3
17 changed files with 28 additions and 29 deletions
|
@ -207,6 +207,7 @@ module.exports = {
|
|||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]panel[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]popover_items[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]progress_inline[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]rule_actions_field[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]selectable_text[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]subtitle[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]text_field_value[\/\\]index.stories.tsx/,
|
||||
|
@ -231,7 +232,6 @@ module.exports = {
|
|||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]mock[\/\\]test_providers.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detection_engine[\/\\]rule_creation[\/\\]components[\/\\]eql_query_edit[\/\\]eql_overview_link.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detection_engine[\/\\]rule_creation[\/\\]components[\/\\]ml_job_link[\/\\]ml_job_link.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detection_engine[\/\\]rule_creation[\/\\]components[\/\\]rule_actions_field[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detection_engine[\/\\]rule_creation[\/\\]components[\/\\]step_about_rule_details[\/\\]index.test.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detection_engine[\/\\]rule_creation[\/\\]components[\/\\]step_content_wrapper[\/\\]index.tsx/,
|
||||
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detection_engine[\/\\]rule_creation[\/\\]components[\/\\]step_panel[\/\\]index.tsx/,
|
||||
|
|
|
@ -36664,7 +36664,6 @@
|
|||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.threatMatchQueryBar.requiredError": "Une requête d'index indicative est requise.",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.thresholdField.thresholdFieldPlaceholderText": "Tous les résultats",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepRuleActions.docsLinkText": "En savoir plus",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepRuleActions.invalidMustacheTemplateErrorMessage": "{key} n'est pas un modèle de moustache valide",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepRuleActions.noReadActionsPrivileges": "Impossible de créer des actions de règle. Vous ne disposez pas des autorisations \"Lire\" pour le plug-in \"Actions\".",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepRuleActions.snoozeDescription": "Choisissez quand effectuer des actions ou les mettre en sommeil. Les notifications ne sont pas créées pour des actions répétées. {docs}.",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepScheduleRule.completeWithEnablingTitle": "Créer et activer la règle",
|
||||
|
|
|
@ -36636,7 +36636,6 @@
|
|||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.threatMatchQueryBar.requiredError": "インジケーターインデックスクエリが必要です。",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.thresholdField.thresholdFieldPlaceholderText": "すべての結果",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepRuleActions.docsLinkText": "詳細",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepRuleActions.invalidMustacheTemplateErrorMessage": "{key}は有効なmustacheテンプレートではありません",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepRuleActions.noReadActionsPrivileges": "ルールアクションを作成できません。「Actions」プラグインの「読み取り」アクセス権がありません。",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepRuleActions.snoozeDescription": "いつアクションを実行するか、いつアクションをスヌーズするかを選択します。スヌーズされたアクションに対しては通知が作成されません。{docs}。",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepScheduleRule.completeWithEnablingTitle": "ルールを作成して有効にする",
|
||||
|
|
|
@ -36699,7 +36699,6 @@
|
|||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.threatMatchQueryBar.requiredError": "指标索引查询必填。",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepDefineRule.thresholdField.thresholdFieldPlaceholderText": "所有结果",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepRuleActions.docsLinkText": "了解详情",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepRuleActions.invalidMustacheTemplateErrorMessage": "{key} 不是有效的 Mustache 模板",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepRuleActions.noReadActionsPrivileges": "无法创建规则操作。您对“操作”插件没有“读”权限。",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepRuleActions.snoozeDescription": "选择执行操作的时间,或暂停这些操作。没有为已暂停操作创建通知。{docs}。",
|
||||
"xpack.securitySolution.detectionEngine.createRule.stepScheduleRule.completeWithEnablingTitle": "创建并启用规则",
|
||||
|
|
|
@ -9,10 +9,10 @@ import React from 'react';
|
|||
import { shallow } from 'enzyme';
|
||||
|
||||
import { RuleActionsField } from '.';
|
||||
import { useForm, Form } from '../../../../shared_imports';
|
||||
import { useKibana } from '../../../../common/lib/kibana';
|
||||
import { useFormFieldMock } from '../../../../common/mock';
|
||||
jest.mock('../../../../common/lib/kibana');
|
||||
import { useForm, Form } from '../../../shared_imports';
|
||||
import { useKibana } from '../../lib/kibana';
|
||||
import { useFormFieldMock } from '../../mock';
|
||||
jest.mock('../../lib/kibana');
|
||||
|
||||
describe('RuleActionsField', () => {
|
||||
it('should not render ActionForm if no actions are supported', () => {
|
|
@ -10,6 +10,7 @@ import { EuiSpacer, EuiCallOut, EuiText } from '@elastic/eui';
|
|||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import deepMerge from 'deepmerge';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
|
||||
import styled from 'styled-components';
|
||||
|
||||
import type {
|
||||
|
@ -24,10 +25,10 @@ import type {
|
|||
import { SecurityConnectorFeatureId } from '@kbn/actions-plugin/common';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
import { NOTIFICATION_DEFAULT_FREQUENCY } from '../../../../../common/constants';
|
||||
import type { FieldHook } from '../../../../shared_imports';
|
||||
import { useFormContext } from '../../../../shared_imports';
|
||||
import { useKibana } from '../../../../common/lib/kibana';
|
||||
import { NOTIFICATION_DEFAULT_FREQUENCY } from '../../../../common/constants';
|
||||
import type { FieldHook } from '../../../shared_imports';
|
||||
import { useFormContext } from '../../../shared_imports';
|
||||
import { useKibana } from '../../lib/kibana';
|
||||
import {
|
||||
FORM_CUSTOM_FREQUENCY_OPTION,
|
||||
FORM_ERRORS_TITLE,
|
|
@ -10,7 +10,7 @@ import { startCase } from 'lodash/fp';
|
|||
|
||||
export const INVALID_MUSTACHE_TEMPLATE = (paramKey: string) =>
|
||||
i18n.translate(
|
||||
'xpack.securitySolution.detectionEngine.createRule.stepRuleActions.invalidMustacheTemplateErrorMessage',
|
||||
'xpack.securitySolution.ruleActions.validation.invalidMustacheTemplateErrorMessage',
|
||||
{
|
||||
defaultMessage: '{key} is not valid mustache template',
|
||||
values: {
|
|
@ -8,7 +8,7 @@
|
|||
import { actionTypeRegistryMock } from '@kbn/triggers-actions-ui-plugin/public/application/action_type_registry.mock';
|
||||
import { getActionTypeName, validateMustache, validateActionParams } from './utils';
|
||||
|
||||
describe('stepRuleActions utils', () => {
|
||||
describe('RuleActions utils', () => {
|
||||
describe('getActionTypeName', () => {
|
||||
it('should return capitalized action type name', () => {
|
||||
expect(getActionTypeName('.slack')).toEqual('Slack');
|
|
@ -8,7 +8,7 @@
|
|||
import { validateSingleAction, validateRuleActionsField } from './validate_rule_actions_field';
|
||||
import { getActionTypeName, validateMustache, validateActionParams } from './utils';
|
||||
import { actionTypeRegistryMock } from '@kbn/triggers-actions-ui-plugin/public/application/action_type_registry.mock';
|
||||
import type { FormHook } from '../../../../../shared_imports';
|
||||
import type { FormHook } from '../../../../shared_imports';
|
||||
jest.mock('./utils');
|
||||
|
||||
describe('validate_rule_actions_field', () => {
|
|
@ -13,14 +13,13 @@ import type {
|
|||
ValidationResponsePromise,
|
||||
} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
|
||||
import type {
|
||||
ActionTypeRegistryContract,
|
||||
RuleAction,
|
||||
ActionTypeRegistryContract,
|
||||
} from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { validateActionFilterQuery } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import type { RuleActionsFormData } from '../../../../../detection_engine/rule_management_ui/components/rules_table/bulk_actions/forms/rule_actions_form';
|
||||
import type { ActionsStepRule } from '../../../../../detection_engine/common/types';
|
||||
import type { ERROR_CODE, ValidationFunc } from '../../../../../shared_imports';
|
||||
import { getActionTypeName, validateActionParams, validateMustache } from './utils';
|
||||
|
||||
import type { FormData, ValidationFunc, ERROR_CODE } from '../../../../shared_imports';
|
||||
import { getActionTypeName, validateMustache, validateActionParams } from './utils';
|
||||
|
||||
export const DEFAULT_VALIDATION_TIMEOUT = 100;
|
||||
|
||||
|
@ -37,8 +36,10 @@ export const validateSingleAction = async (
|
|||
|
||||
export const validateRuleActionsField =
|
||||
(actionTypeRegistry: ActionTypeRegistryContract) =>
|
||||
async (...data: Parameters<ValidationFunc>): ValidationResponsePromise<ERROR_CODE> => {
|
||||
const [{ value, path }] = data as [{ value: RuleAction[]; path: string }];
|
||||
async (
|
||||
...data: Parameters<ValidationFunc<FormData, string, RuleAction[]>>
|
||||
): ValidationResponsePromise<ERROR_CODE> => {
|
||||
const [{ value, path }] = data;
|
||||
|
||||
const errors = [];
|
||||
for (const actionItem of value) {
|
||||
|
@ -75,11 +76,11 @@ export const validateRuleActionsField =
|
|||
* @param defaultValidationTimeout
|
||||
*/
|
||||
export const debouncedValidateRuleActionsField =
|
||||
(
|
||||
<I extends FormData>(
|
||||
actionTypeRegistry: ActionTypeRegistryContract,
|
||||
defaultValidationTimeout = DEFAULT_VALIDATION_TIMEOUT
|
||||
) =>
|
||||
(data: ValidationFuncArg<ActionsStepRule | RuleActionsFormData>): ValidationResponsePromise => {
|
||||
(data: ValidationFuncArg<I, RuleAction[]>): ValidationResponsePromise => {
|
||||
let isCanceled = false;
|
||||
const promise: ValidationCancelablePromise = new Promise((resolve) => {
|
||||
setTimeout(() => {
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import type { ActionTypeRegistryContract } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { debouncedValidateRuleActionsField } from '../../../../detections/containers/detection_engine/rules/validate_rule_actions_field';
|
||||
import { debouncedValidateRuleActionsField } from '../../../../common/containers/rule_actions/validate_rule_actions_field';
|
||||
|
||||
import type { FormSchema } from '../../../../shared_imports';
|
||||
import type { ActionsStepRule } from '../../../common/types';
|
||||
|
|
|
@ -15,13 +15,13 @@ import type {
|
|||
ActionVariables,
|
||||
} from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { UseArray } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
|
||||
import { RuleActionsField } from '../../../../common/components/rule_actions_field';
|
||||
import type { RuleObjectId } from '../../../../../common/api/detection_engine/model/rule_schema';
|
||||
import { ResponseActionsForm } from '../../../rule_response_actions/response_actions_form';
|
||||
import type { ActionsStepRule, RuleStepProps } from '../../../common/types';
|
||||
import type { FormHook } from '../../../../shared_imports';
|
||||
import { Form, UseField } from '../../../../shared_imports';
|
||||
import { StepContentWrapper } from '../step_content_wrapper';
|
||||
import { RuleActionsField } from '../rule_actions_field';
|
||||
import { useKibana } from '../../../../common/lib/kibana';
|
||||
import { useFetchConnectorsQuery } from '../../../rule_management/api/hooks/use_fetch_connectors_query';
|
||||
import { useFetchConnectorTypesQuery } from '../../../rule_management/api/hooks/use_fetch_connector_types_query';
|
||||
|
|
|
@ -13,6 +13,7 @@ import type {
|
|||
ActionTypeRegistryContract,
|
||||
} from '@kbn/triggers-actions-ui-plugin/public';
|
||||
|
||||
import { RuleActionsField } from '../../../../../../common/components/rule_actions_field';
|
||||
import { transformAlertToNormalizedRuleAction } from '../../../../../../../common/detection_engine/transform_actions';
|
||||
import type { FormSchema } from '../../../../../../shared_imports';
|
||||
import {
|
||||
|
@ -33,8 +34,7 @@ import { useKibana } from '../../../../../../common/lib/kibana';
|
|||
|
||||
import { getAllActionMessageParams } from '../../../../../common/helpers';
|
||||
|
||||
import { RuleActionsField } from '../../../../../rule_creation/components/rule_actions_field';
|
||||
import { debouncedValidateRuleActionsField } from '../../../../../../detections/containers/detection_engine/rules/validate_rule_actions_field';
|
||||
import { debouncedValidateRuleActionsField } from '../../../../../../common/containers/rule_actions/validate_rule_actions_field';
|
||||
|
||||
const CommonUseField = getUseField({ component: Field });
|
||||
|
||||
|
|
|
@ -10,11 +10,11 @@ import { EuiCallOut, EuiSpacer } from '@elastic/eui';
|
|||
import { map, reduce } from 'lodash';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import { ResponseActionsWrapper } from './response_actions_wrapper';
|
||||
import { FORM_ERRORS_TITLE } from '../rule_creation/components/rule_actions_field/translations';
|
||||
import { ResponseActionsHeader } from './response_actions_header';
|
||||
import type { ArrayItem, FormHook } from '../../shared_imports';
|
||||
import { useSupportedResponseActionTypes } from './use_supported_response_action_types';
|
||||
import { getActionDetails } from './constants';
|
||||
import { FORM_ERRORS_TITLE } from '../../common/components/rule_actions_field/translations';
|
||||
|
||||
interface ResponseActionsFormProps {
|
||||
items: ArrayItem[];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue