diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/three_way_diff/three_way_diff.ts b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/three_way_diff/three_way_diff.ts index 7b71bb6f16c7a..c8c4238709849 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/three_way_diff/three_way_diff.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/three_way_diff/three_way_diff.ts @@ -131,6 +131,7 @@ export interface ThreeWayDiff { * True if: * - base=A, current=A, target=B * - base=A, current=B, target=C + * - base=, current=A, target=B */ has_update: boolean; diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/three_way_diff/three_way_diff_conflict.ts b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/three_way_diff/three_way_diff_conflict.ts index f33c52d33abfc..541c51d4f571f 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/three_way_diff/three_way_diff_conflict.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/model/diff/three_way_diff/three_way_diff_conflict.ts @@ -7,8 +7,8 @@ /** * Enum of possible conflict outcomes of a three-way diff: - * - NON_SOLVABLE_CONFLICT: current != target and we couldn't automatically resolve the conflict between them - * - SOLVABLE_CONFLICT: current != target and we automatically resolved the conflict between them + * - NON_SOLVABLE: current != target and we couldn't automatically resolve the conflict between them + * - SOLVABLE: current != target and we automatically resolved the conflict between them * - NO_CONFLICT: * - current == target (value won't change) * - current != target && current == base (stock rule will get a new value) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/helpers.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/helpers.ts index 9810cd4882cc7..08e4c9535ae91 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/helpers.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/helpers.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { isPlainObject } from 'lodash'; import type { Filter } from '@kbn/es-query'; import type { DiffableAllFields, @@ -77,16 +78,12 @@ export function getQueryLanguageLabel(language: string) { } /** - * Assigns type `Filter` to items that have a `meta` property. Removes any other items. + * Assigns type `Filter[]` to an array if every item in it has a `meta` property. */ -export function typeCheckFilters(filters: unknown[]): Filter[] { - return filters.filter((f) => { - if (typeof f === 'object' && f !== null && 'meta' in f) { - return true; - } - - return false; - }) as Filter[]; +export function isFilters(maybeFilters: unknown[]): maybeFilters is Filter[] { + return maybeFilters.every( + (f) => typeof f === 'object' && f !== null && 'meta' in f && isPlainObject(f.meta) + ); } type DataSourceProps = diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_about_section.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_about_section.tsx index c7c9ec3ca732d..1d2e93df8e7f7 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_about_section.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_about_section.tsx @@ -256,7 +256,7 @@ interface TagsProps { tags: string[]; } -const Tags = ({ tags }: TagsProps) => ( +export const Tags = ({ tags }: TagsProps) => ( ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/common_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/common_rule_field_readonly.tsx new file mode 100644 index 0000000000000..35bde351bbeb6 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/common_rule_field_readonly.tsx @@ -0,0 +1,91 @@ +/* + * 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 React from 'react'; +import type { + DiffableCommonFields, + DiffableRule, +} from '../../../../../../../common/api/detection_engine'; +import { RelatedIntegrationsReadOnly } from './fields/related_integrations/related_integrations'; +import { RequiredFieldsReadOnly } from './fields/required_fields/required_fields'; +import { SeverityMappingReadOnly } from './fields/severity_mapping/severity_mapping'; +import { RiskScoreMappingReadOnly } from './fields/risk_score_mapping/risk_score_mapping'; +import { ThreatReadOnly } from './fields/threat/threat'; +import { NameReadOnly } from './fields/name/name'; +import { TagsReadOnly } from './fields/tags/tags'; +import { DescriptionReadOnly } from './fields/description/description'; +import { assertUnreachable } from '../../../../../../../common/utility_types'; + +interface CommonRuleFieldReadOnlyProps { + fieldName: keyof DiffableCommonFields; + finalDiffableRule: DiffableRule; +} + +// eslint-disable-next-line complexity +export function CommonRuleFieldReadOnly({ + fieldName, + finalDiffableRule, +}: CommonRuleFieldReadOnlyProps) { + switch (fieldName) { + case 'author': + return null; + case 'building_block': + return null; + case 'description': + return ; + case 'exceptions_list': + return null; + case 'investigation_fields': + return null; + case 'false_positives': + return null; + case 'license': + return null; + case 'max_signals': + return null; + case 'name': + return ; + case 'note': + return null; + case 'related_integrations': + return ( + + ); + case 'required_fields': + return ; + case 'risk_score_mapping': + return ; + case 'rule_schedule': + return null; + case 'severity_mapping': + return ; + case 'tags': + return ; + case 'threat': + return ; + case 'references': + return null; + case 'risk_score': + return null; + case 'rule_id': + return null; + case 'rule_name_override': + return null; + case 'setup': + return null; + case 'severity': + return null; + case 'timestamp_override': + return null; + case 'timeline_template': + return null; + case 'version': + return null; + default: + return assertUnreachable(fieldName); + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/custom_query_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/custom_query_rule_field_readonly.tsx new file mode 100644 index 0000000000000..3d22d268438c4 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/custom_query_rule_field_readonly.tsx @@ -0,0 +1,36 @@ +/* + * 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 React from 'react'; +import type { DiffableCustomQueryFields } from '../../../../../../../common/api/detection_engine'; +import { DataSourceReadOnly } from './fields/data_source/data_source'; +import { KqlQueryReadOnly } from './fields/kql_query'; + +interface CustomQueryRuleFieldReadOnlyProps { + fieldName: keyof DiffableCustomQueryFields; + finalDiffableRule: DiffableCustomQueryFields; +} + +export function CustomQueryRuleFieldReadOnly({ + fieldName, + finalDiffableRule, +}: CustomQueryRuleFieldReadOnlyProps) { + switch (fieldName) { + case 'data_source': + return ; + case 'kql_query': + return ( + + ); + default: + return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/eql_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/eql_rule_field_readonly.tsx new file mode 100644 index 0000000000000..126775965724b --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/eql_rule_field_readonly.tsx @@ -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 React from 'react'; +import type { DiffableEqlFields } from '../../../../../../../common/api/detection_engine'; +import { DataSourceReadOnly } from './fields/data_source/data_source'; +import { EqlQueryReadOnly } from './fields/eql_query/eql_query'; + +interface EqlRuleFieldReadOnlyProps { + fieldName: keyof DiffableEqlFields; + finalDiffableRule: DiffableEqlFields; +} + +export function EqlRuleFieldReadOnly({ fieldName, finalDiffableRule }: EqlRuleFieldReadOnlyProps) { + switch (fieldName) { + case 'data_source': + return ; + case 'eql_query': + return ( + + ); + case 'type': + return null; + default: + return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/esql_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/esql_rule_field_readonly.tsx new file mode 100644 index 0000000000000..755ad6b1b4789 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/esql_rule_field_readonly.tsx @@ -0,0 +1,29 @@ +/* + * 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 React from 'react'; +import type { DiffableEsqlFields } from '../../../../../../../common/api/detection_engine'; +import { EsqlQueryReadOnly } from './fields/esql_query/esql_query'; + +interface EsqlRuleFieldReadOnlyProps { + fieldName: keyof DiffableEsqlFields; + finalDiffableRule: DiffableEsqlFields; +} + +export function EsqlRuleFieldReadOnly({ + fieldName, + finalDiffableRule, +}: EsqlRuleFieldReadOnlyProps) { + switch (fieldName) { + case 'esql_query': + return ; + case 'type': + return null; + default: + return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/field_readonly.tsx index f3d436ad7a26a..d8d31e343278b 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/field_readonly.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/field_readonly.tsx @@ -5,85 +5,105 @@ * 2.0. */ -import React from 'react'; -import type { DiffableAllFields } from '../../../../../../../common/api/detection_engine'; -import { KqlQueryReadOnly } from './fields/kql_query'; -import { DataSourceReadOnly } from './fields/data_source/data_source'; -import { EqlQueryReadOnly } from './fields/eql_query/eql_query'; -import { EsqlQueryReadOnly } from './fields/esql_query/esql_query'; -import { MachineLearningJobIdReadOnly } from './fields/machine_learning_job_id/machine_learning_job_id'; -import { RelatedIntegrationsReadOnly } from './fields/related_integrations/related_integrations'; -import { RequiredFieldsReadOnly } from './fields/required_fields/required_fields'; -import { SeverityMappingReadOnly } from './fields/severity_mapping/severity_mapping'; -import { RiskScoreMappingReadOnly } from './fields/risk_score_mapping/risk_score_mapping'; -import { ThreatMappingReadOnly } from './fields/threat_mapping/threat_mapping'; -import { ThreatReadOnly } from './fields/threat/threat'; -import { ThreatIndexReadOnly } from './fields/threat_index/threat_index'; -import { ThreatIndicatorPathReadOnly } from './fields/threat_indicator_path/threat_indicator_path'; -import { ThreatQueryReadOnly } from './fields/threat_query/threat_query'; +import React, { useMemo } from 'react'; +import { DiffableCommonFields } from '../../../../../../../common/api/detection_engine'; +import type { + DiffableRule, + DiffableCustomQueryFields, + DiffableSavedQueryFields, + DiffableEqlFields, + DiffableThreatMatchFields, + DiffableThresholdFields, + DiffableNewTermsFields, + DiffableEsqlFields, + DiffableMachineLearningFields, +} from '../../../../../../../common/api/detection_engine'; +import { assertUnreachable } from '../../../../../../../common/utility_types'; +import { CustomQueryRuleFieldReadOnly } from './custom_query_rule_field_readonly'; +import { SavedQueryRuleFieldReadOnly } from './saved_query_rule_field_readonly'; +import { EqlRuleFieldReadOnly } from './eql_rule_field_readonly'; +import { EsqlRuleFieldReadOnly } from './esql_rule_field_readonly'; +import { ThreatMatchRuleFieldReadOnly } from './threat_match_rule_field_readonly'; +import { ThresholdRuleFieldReadOnly } from './threshold_rule_field_readonly'; +import { MachineLearningRuleFieldReadOnly } from './machine_learning_rule_field_readonly'; +import { NewTermsRuleFieldReadOnly } from './new_terms_rule_field_readonly'; +import { CommonRuleFieldReadOnly } from './common_rule_field_readonly'; interface FieldReadOnlyProps { - fieldName: keyof DiffableAllFields; - finalDiffableRule: DiffableAllFields; + fieldName: string; + finalDiffableRule: DiffableRule; } export function FieldReadOnly({ fieldName, finalDiffableRule }: FieldReadOnlyProps) { - switch (fieldName) { - case 'data_source': - return ; - case 'eql_query': + const { data: commonField } = useMemo( + () => DiffableCommonFields.keyof().safeParse(fieldName), + [fieldName] + ); + + if (commonField) { + return ( + + ); + } + + switch (finalDiffableRule.type) { + case 'query': + return ( + + ); + case 'saved_query': return ( - ); - case 'esql_query': - return ; - case 'kql_query': + case 'eql': return ( - ); - case 'machine_learning_job_id': + case 'esql': return ( - ); - case 'related_integrations': + case 'threat_match': return ( - + + ); + case 'threshold': + return ( + ); - case 'required_fields': - return ; - case 'risk_score_mapping': - return ; - case 'severity_mapping': - return ; - case 'threat': - return ; - case 'threat_index': - return ; - case 'threat_indicator_path': + case 'machine_learning': return ( - ); - case 'threat_mapping': - return ; - case 'threat_query': + case 'new_terms': return ( - ); default: - return null; + return assertUnreachable(finalDiffableRule); } } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.stories.tsx index 6ffe47a254de9..9deebf794c241 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.stories.tsx @@ -8,12 +8,13 @@ import React from 'react'; import type { Story } from '@storybook/react'; import { FieldReadOnly } from '../../field_readonly'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; import { dataSourceWithDataView, dataSourceWithIndexPatterns, mockDataView, + mockCustomQueryRule, } from '../../storybook/mocks'; export default { @@ -22,17 +23,14 @@ export default { }; interface TemplateProps { - finalDiffableRule: Partial; + finalDiffableRule: DiffableRule; kibanaServicesMock?: Record; } const Template: Story = (args) => { return ( - + ); }; @@ -40,17 +38,17 @@ const Template: Story = (args) => { export const DataSourceWithIndexPatterns = Template.bind({}); DataSourceWithIndexPatterns.args = { - finalDiffableRule: { + finalDiffableRule: mockCustomQueryRule({ data_source: dataSourceWithIndexPatterns, - }, + }), }; export const DataSourceWithDataView = Template.bind({}); DataSourceWithDataView.args = { - finalDiffableRule: { + finalDiffableRule: mockCustomQueryRule({ data_source: dataSourceWithDataView, - }, + }), kibanaServicesMock: { data: { dataViews: { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.tsx index 29518981011fa..2a7bff6ff8b2d 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/data_source/data_source.tsx @@ -8,13 +8,13 @@ import React from 'react'; import { EuiDescriptionList } from '@elastic/eui'; import { DataSourceType } from '../../../../../../../../../common/api/detection_engine'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { RuleDataSource } from '../../../../../../../../../common/api/detection_engine'; import { Index, DataViewId, DataViewIndexPattern } from '../../../../rule_definition_section'; import * as ruleDetailsI18n from '../../../../translations'; import { assertUnreachable } from '../../../../../../../../../common/utility_types'; interface DataSourceReadOnlyProps { - dataSource: DiffableAllFields['data_source']; + dataSource?: RuleDataSource; } export function DataSourceReadOnly({ dataSource }: DataSourceReadOnlyProps) { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/description/description.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/description/description.stories.tsx new file mode 100644 index 0000000000000..ba094ecfe54f9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/description/description.stories.tsx @@ -0,0 +1,35 @@ +/* + * 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 React from 'react'; +import type { Story } from '@storybook/react'; +import { DescriptionReadOnly } from './description'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: DescriptionReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/description', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + description: + "Identifies the occurrence of a security alert from the Google Workspace alerts center. Google Workspace's security alert center provides an overview of actionable alerts that may be affecting an organization's domain. An alert is a warning of a potential security issue that Google has detected.", + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/description/description.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/description/description.tsx new file mode 100644 index 0000000000000..add624ba15a6d --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/description/description.tsx @@ -0,0 +1,36 @@ +/* + * 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 React from 'react'; +import { EuiDescriptionList } from '@elastic/eui'; +import * as ruleDetailsI18n from '../../../../translations'; +import type { RuleDescription } from '../../../../../../../../../common/api/detection_engine'; + +interface DescriptionReadOnlyProps { + description: RuleDescription; +} + +export function DescriptionReadOnly({ description }: DescriptionReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} + +interface DescriptionProps { + description: RuleDescription; +} + +function Description({ description }: DescriptionProps) { + return <>{description}; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.stories.tsx index 205e87e209068..af835c5a92779 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.stories.tsx @@ -8,7 +8,7 @@ import React from 'react'; import type { Story } from '@storybook/react'; import { FieldReadOnly } from '../../field_readonly'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; import { EqlQueryReadOnly } from './eql_query'; import { @@ -16,6 +16,7 @@ import { dataSourceWithIndexPatterns, eqlQuery, mockDataView, + mockEqlRule, } from '../../storybook/mocks'; export default { @@ -24,17 +25,14 @@ export default { }; interface TemplateProps { - finalDiffableRule: Partial; + finalDiffableRule: DiffableRule; kibanaServicesMock?: Record; } const Template: Story = (args) => { return ( - + ); }; @@ -42,10 +40,10 @@ const Template: Story = (args) => { export const EqlQueryWithIndexPatterns = Template.bind({}); EqlQueryWithIndexPatterns.args = { - finalDiffableRule: { + finalDiffableRule: mockEqlRule({ eql_query: eqlQuery, data_source: dataSourceWithIndexPatterns, - }, + }), kibanaServicesMock: { data: { dataViews: { @@ -58,10 +56,10 @@ EqlQueryWithIndexPatterns.args = { export const EqlQueryWithDataView = Template.bind({}); EqlQueryWithDataView.args = { - finalDiffableRule: { + finalDiffableRule: mockEqlRule({ eql_query: eqlQuery, data_source: dataSourceWithDataView, - }, + }), kibanaServicesMock: { data: { dataViews: { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.tsx index 3238e7bb7eeef..f94f0bbfbe6c8 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/eql_query/eql_query.tsx @@ -8,14 +8,17 @@ import React from 'react'; import { EuiDescriptionList } from '@elastic/eui'; import type { EuiDescriptionListProps } from '@elastic/eui'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { + RuleDataSource, + RuleEqlQuery, +} from '../../../../../../../../../common/api/detection_engine'; import * as descriptionStepI18n from '../../../../../../../rule_creation_ui/components/description_step/translations'; import { Query, Filters } from '../../../../rule_definition_section'; -import { getDataSourceProps, typeCheckFilters } from '../../../../helpers'; +import { getDataSourceProps, isFilters } from '../../../../helpers'; interface EqlQueryReadOnlyProps { - eqlQuery: DiffableAllFields['eql_query']; - dataSource: DiffableAllFields['data_source']; + eqlQuery: RuleEqlQuery; + dataSource?: RuleDataSource; } export function EqlQueryReadOnly({ eqlQuery, dataSource }: EqlQueryReadOnlyProps) { @@ -26,14 +29,12 @@ export function EqlQueryReadOnly({ eqlQuery, dataSource }: EqlQueryReadOnlyProps }, ]; - const filters = typeCheckFilters(eqlQuery.filters); - - if (filters.length > 0) { + if (isFilters(eqlQuery.filters) && eqlQuery.filters.length > 0) { const dataSourceProps = getDataSourceProps(dataSource); listItems.push({ title: descriptionStepI18n.FILTERS_LABEL, - description: , + description: , }); } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/esql_query/esql_query.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/esql_query/esql_query.stories.tsx index cda1c99a218bb..664294dbe768c 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/esql_query/esql_query.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/esql_query/esql_query.stories.tsx @@ -8,7 +8,8 @@ import React from 'react'; import type { Story } from '@storybook/react'; import { FieldReadOnly } from '../../field_readonly'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockEsqlRule } from '../../storybook/mocks'; export default { component: FieldReadOnly, @@ -16,25 +17,20 @@ export default { }; interface TemplateProps { - finalDiffableRule: Partial; + finalDiffableRule: DiffableRule; } const Template: Story = (args) => { - return ( - - ); + return ; }; export const Default = Template.bind({}); Default.args = { - finalDiffableRule: { + finalDiffableRule: mockEsqlRule({ esql_query: { query: `SELECT user.name, source.ip FROM "logs-*" WHERE event.action = 'user_login' AND event.outcome = 'failure'`, language: 'esql', }, - }, + }), }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/esql_query/esql_query.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/esql_query/esql_query.tsx index ec110bd034b67..9277d2ded7a7d 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/esql_query/esql_query.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/esql_query/esql_query.tsx @@ -9,10 +9,10 @@ import React from 'react'; import { EuiDescriptionList } from '@elastic/eui'; import * as descriptionStepI18n from '../../../../../../../rule_creation_ui/components/description_step/translations'; import { Query } from '../../../../rule_definition_section'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { RuleEsqlQuery } from '../../../../../../../../../common/api/detection_engine'; interface EsqlQueryReadonlyProps { - esqlQuery: DiffableAllFields['esql_query']; + esqlQuery: RuleEsqlQuery; } export function EsqlQueryReadOnly({ esqlQuery }: EsqlQueryReadonlyProps) { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/index.tsx index a2dd75e188a0c..d5bea0866c22f 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/index.tsx @@ -8,7 +8,8 @@ import React from 'react'; import { KqlQueryType } from '../../../../../../../../../common/api/detection_engine'; import type { - DiffableAllFields, + DiffableRuleTypes, + RuleDataSource, RuleKqlQuery, } from '../../../../../../../../../common/api/detection_engine'; import { InlineKqlQueryReadOnly } from './inline_kql_query'; @@ -17,8 +18,8 @@ import { assertUnreachable } from '../../../../../../../../../common/utility_typ interface KqlQueryReadOnlyProps { kqlQuery: RuleKqlQuery; - dataSource: DiffableAllFields['data_source']; - ruleType: DiffableAllFields['type']; + dataSource?: RuleDataSource; + ruleType: DiffableRuleTypes; } export function KqlQueryReadOnly({ kqlQuery, dataSource, ruleType }: KqlQueryReadOnlyProps) { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/inline_kql_query.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/inline_kql_query.tsx index a70909745d8dc..54d3836573ab5 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/inline_kql_query.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/inline_kql_query.tsx @@ -9,13 +9,13 @@ import React from 'react'; import { EuiDescriptionList } from '@elastic/eui'; import type { EuiDescriptionListProps } from '@elastic/eui'; import type { - DiffableAllFields, InlineKqlQuery, + RuleDataSource, } from '../../../../../../../../../common/api/detection_engine'; import { Query, Filters } from '../../../../rule_definition_section'; import * as ruleDetailsI18n from '../../../../translations'; import * as descriptionStepI18n from '../../../../../../../rule_creation_ui/components/description_step/translations'; -import { getDataSourceProps, getQueryLanguageLabel, typeCheckFilters } from '../../../../helpers'; +import { getDataSourceProps, getQueryLanguageLabel, isFilters } from '../../../../helpers'; const defaultI18nLabels = { query: descriptionStepI18n.QUERY_LABEL, @@ -25,7 +25,7 @@ const defaultI18nLabels = { interface InlineQueryProps { kqlQuery: InlineKqlQuery; - dataSource?: DiffableAllFields['data_source']; + dataSource?: RuleDataSource; i18nLabels?: { query: string; language: string; @@ -49,14 +49,12 @@ export function InlineKqlQueryReadOnly({ }, ]; - const filters = typeCheckFilters(kqlQuery.filters); - - if (filters.length > 0) { + if (isFilters(kqlQuery.filters) && kqlQuery.filters.length > 0) { const dataSourceProps = getDataSourceProps(dataSource); listItems.push({ title: i18nLabels.filters, - description: , + description: , }); } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/kql_query.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/kql_query.stories.tsx index 61d31d983b183..2b4844ceac5d5 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/kql_query.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/kql_query.stories.tsx @@ -8,18 +8,17 @@ import React from 'react'; import type { Story } from '@storybook/react'; import { FieldReadOnly } from '../../field_readonly'; -import type { - DiffableAllFields, - RuleKqlQuery, -} from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; import { dataSourceWithDataView, dataSourceWithIndexPatterns, inlineKqlQuery, mockDataView, + mockCustomQueryRule, savedKqlQuery, savedQueryResponse, + mockSavedQueryRule, } from '../../storybook/mocks'; export default { @@ -28,17 +27,14 @@ export default { }; interface TemplateProps { - finalDiffableRule: Partial | { kql_query: RuleKqlQuery }; + finalDiffableRule: DiffableRule; kibanaServicesMock?: Record; } const Template: Story = (args) => { return ( - + ); }; @@ -46,10 +42,10 @@ const Template: Story = (args) => { export const InlineKqlQueryWithIndexPatterns = Template.bind({}); InlineKqlQueryWithIndexPatterns.args = { - finalDiffableRule: { + finalDiffableRule: mockCustomQueryRule({ kql_query: inlineKqlQuery, data_source: dataSourceWithIndexPatterns, - }, + }), kibanaServicesMock: { data: { dataViews: { @@ -62,10 +58,10 @@ InlineKqlQueryWithIndexPatterns.args = { export const InlineKqlQueryWithDataView = Template.bind({}); InlineKqlQueryWithDataView.args = { - finalDiffableRule: { + finalDiffableRule: mockCustomQueryRule({ kql_query: inlineKqlQuery, data_source: dataSourceWithDataView, - }, + }), kibanaServicesMock: { data: { dataViews: { @@ -82,9 +78,9 @@ export const InlineKqlQueryWithoutDataSource = Template.bind({}); Component would fall back to the default index pattern in such case. */ InlineKqlQueryWithoutDataSource.args = { - finalDiffableRule: { + finalDiffableRule: mockCustomQueryRule({ kql_query: inlineKqlQuery, - }, + }), kibanaServicesMock: { data: { dataViews: { @@ -97,11 +93,11 @@ InlineKqlQueryWithoutDataSource.args = { export const SavedKqlQueryWithIndexPatterns = Template.bind({}); SavedKqlQueryWithIndexPatterns.args = { - finalDiffableRule: { + finalDiffableRule: mockSavedQueryRule({ kql_query: savedKqlQuery, data_source: dataSourceWithIndexPatterns, type: 'saved_query', - }, + }), kibanaServicesMock: { data: { dataViews: { @@ -117,11 +113,11 @@ SavedKqlQueryWithIndexPatterns.args = { export const SavedKqlQueryWithDataView = Template.bind({}); SavedKqlQueryWithDataView.args = { - finalDiffableRule: { + finalDiffableRule: mockSavedQueryRule({ kql_query: savedKqlQuery, data_source: dataSourceWithDataView, type: 'saved_query', - }, + }), kibanaServicesMock: { data: { dataViews: { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/saved_kql_query.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/saved_kql_query.tsx index d7741f41af820..5f50a9c1b9eae 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/saved_kql_query.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/kql_query/saved_kql_query.tsx @@ -10,8 +10,8 @@ import { EuiDescriptionList } from '@elastic/eui'; import type { EuiDescriptionListProps } from '@elastic/eui'; import type { SavedKqlQuery, - DiffableRule, - DiffableAllFields, + RuleDataSource, + DiffableRuleTypes, } from '../../../../../../../../../common/api/detection_engine'; import { Query, SavedQueryName, Filters } from '../../../../rule_definition_section'; import * as ruleDetailsI18n from '../../../../translations'; @@ -21,8 +21,8 @@ import { getDataSourceProps, getQueryLanguageLabel } from '../../../../helpers'; interface SavedQueryProps { kqlQuery: SavedKqlQuery; - dataSource?: DiffableAllFields['data_source']; - ruleType: DiffableRule['type']; + dataSource?: RuleDataSource; + ruleType: DiffableRuleTypes; } export function SavedKqlQueryReadOnly({ kqlQuery, dataSource, ruleType }: SavedQueryProps) { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/machine_learning_job_id/machine_learning_job_id.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/machine_learning_job_id/machine_learning_job_id.stories.tsx index 4d334f3aa57ec..8dc504b737e00 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/machine_learning_job_id/machine_learning_job_id.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/machine_learning_job_id/machine_learning_job_id.stories.tsx @@ -9,12 +9,13 @@ import React from 'react'; import { useQueryClient } from '@tanstack/react-query'; import type { Story } from '@storybook/react'; import { MachineLearningJobIdReadOnly } from './machine_learning_job_id'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { FieldReadOnly } from '../../field_readonly'; import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; import { GET_MODULES_QUERY_KEY } from '../../../../../../../../common/components/ml_popover/hooks/use_fetch_modules_query'; import { GET_RECOGNIZER_QUERY_KEY } from '../../../../../../../../common/components/ml_popover/hooks/use_fetch_recognizer_query'; import { GET_JOBS_SUMMARY_QUERY_KEY } from '../../../../../../../../common/components/ml/hooks/use_fetch_jobs_summary_query'; +import { mockMachineLearningRule } from '../../storybook/mocks'; export default { component: MachineLearningJobIdReadOnly, @@ -58,7 +59,7 @@ function MockMlData({ children }: { children: React.ReactNode }) { } interface TemplateProps { - finalDiffableRule: Partial; + finalDiffableRule: DiffableRule; } const Template: Story = (args) => { @@ -67,7 +68,7 @@ const Template: Story = (args) => { @@ -77,7 +78,7 @@ const Template: Story = (args) => { export const Default = Template.bind({}); Default.args = { - finalDiffableRule: { + finalDiffableRule: mockMachineLearningRule({ machine_learning_job_id: 'auth_high_count_logon_events', - }, + }), }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/machine_learning_job_id/machine_learning_job_id.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/machine_learning_job_id/machine_learning_job_id.tsx index b177da1467910..570c58539ea84 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/machine_learning_job_id/machine_learning_job_id.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/machine_learning_job_id/machine_learning_job_id.tsx @@ -8,11 +8,11 @@ import React from 'react'; import { EuiDescriptionList } from '@elastic/eui'; import { MachineLearningJobList } from '../../../../rule_definition_section'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { MachineLearningJobId } from '../../../../../../../../../common/api/detection_engine'; import * as ruleDetailsI18n from '../../../../translations'; interface MachineLearningJobIdProps { - machineLearningJobId: DiffableAllFields['machine_learning_job_id']; + machineLearningJobId: MachineLearningJobId; } export function MachineLearningJobIdReadOnly({ machineLearningJobId }: MachineLearningJobIdProps) { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/name/name.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/name/name.stories.tsx new file mode 100644 index 0000000000000..1451d3b70ef8b --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/name/name.stories.tsx @@ -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 React from 'react'; +import type { Story } from '@storybook/react'; +import { NameReadOnly } from './name'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: NameReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/name', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + name: 'Forwarded Google Workspace Security Alert', + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/name/name.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/name/name.tsx new file mode 100644 index 0000000000000..a611f9821d54e --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/name/name.tsx @@ -0,0 +1,36 @@ +/* + * 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 React from 'react'; +import { EuiDescriptionList } from '@elastic/eui'; +import * as ruleDetailsI18n from '../../../../translations'; +import type { RuleName } from '../../../../../../../../../common/api/detection_engine'; + +interface NameReadOnlyProps { + name: RuleName; +} + +export function NameReadOnly({ name }: NameReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} + +interface NameProps { + name: RuleName; +} + +function Name({ name }: NameProps) { + return <>{name}; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/related_integrations/related_integrations.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/related_integrations/related_integrations.stories.tsx index 9855e2f974096..4657b21b0c64e 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/related_integrations/related_integrations.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/related_integrations/related_integrations.stories.tsx @@ -11,7 +11,8 @@ import type { Story } from '@storybook/react'; import { RelatedIntegrationsReadOnly } from './related_integrations'; import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; import { FieldReadOnly } from '../../field_readonly'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; export default { component: RelatedIntegrationsReadOnly, @@ -39,7 +40,7 @@ function MockRelatedIntegrationsData({ children }: { children: React.ReactNode } } interface TemplateProps { - finalDiffableRule: Partial; + finalDiffableRule: DiffableRule; } const Template: Story = (args) => { @@ -48,7 +49,7 @@ const Template: Story = (args) => { @@ -58,7 +59,7 @@ const Template: Story = (args) => { export const Default = Template.bind({}); Default.args = { - finalDiffableRule: { + finalDiffableRule: mockCustomQueryRule({ related_integrations: [{ package: 'endpoint', version: '^8.2.0' }], - }, + }), }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/required_fields/required_fields.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/required_fields/required_fields.stories.tsx index 2957d8ff7ceaf..44d3383ae8227 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/required_fields/required_fields.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/required_fields/required_fields.stories.tsx @@ -8,7 +8,8 @@ import React from 'react'; import type { Story } from '@storybook/react'; import { RequiredFieldsReadOnly } from './required_fields'; import { FieldReadOnly } from '../../field_readonly'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; export default { component: RequiredFieldsReadOnly, @@ -16,25 +17,20 @@ export default { }; interface TemplateProps { - finalDiffableRule: Partial; + finalDiffableRule: DiffableRule; } const Template: Story = (args) => { - return ( - - ); + return ; }; export const Default = Template.bind({}); Default.args = { - finalDiffableRule: { + finalDiffableRule: mockCustomQueryRule({ required_fields: [ { name: 'event.kind', type: 'keyword', ecs: true }, { name: 'event.module', type: 'keyword', ecs: true }, ], - }, + }), }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score_mapping/risk_score_mapping.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score_mapping/risk_score_mapping.stories.tsx index 76775d6da4586..40c8644ffd3ea 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score_mapping/risk_score_mapping.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score_mapping/risk_score_mapping.stories.tsx @@ -8,8 +8,9 @@ import React from 'react'; import type { Story } from '@storybook/react'; import { FieldReadOnly } from '../../field_readonly'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { RiskScoreMappingReadOnly } from './risk_score_mapping'; +import { mockCustomQueryRule } from '../../storybook/mocks'; export default { component: RiskScoreMappingReadOnly, @@ -18,22 +19,19 @@ export default { }; interface TemplateProps { - finalDiffableRule: Partial; + finalDiffableRule: DiffableRule; } const Template: Story = (args) => { return ( - + ); }; export const Default = Template.bind({}); Default.args = { - finalDiffableRule: { + finalDiffableRule: mockCustomQueryRule({ risk_score_mapping: [{ field: 'event.risk_score', operator: 'equals', value: '' }], - }, + }), }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity_mapping/severity_mapping.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity_mapping/severity_mapping.stories.tsx index 92d7b95b17c2b..6a4b365a86db5 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity_mapping/severity_mapping.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity_mapping/severity_mapping.stories.tsx @@ -8,8 +8,9 @@ import React from 'react'; import type { Story } from '@storybook/react'; import { FieldReadOnly } from '../../field_readonly'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { SeverityMappingReadOnly } from './severity_mapping'; +import { mockCustomQueryRule } from '../../storybook/mocks'; export default { component: SeverityMappingReadOnly, @@ -18,22 +19,17 @@ export default { }; interface TemplateProps { - finalDiffableRule: Partial; + finalDiffableRule: DiffableRule; } const Template: Story = (args) => { - return ( - - ); + return ; }; export const Default = Template.bind({}); Default.args = { - finalDiffableRule: { + finalDiffableRule: mockCustomQueryRule({ severity_mapping: [ { field: 'event.severity', @@ -48,5 +44,5 @@ Default.args = { value: 'VERY HIGH', }, ], - }, + }), }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tags/tags.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tags/tags.stories.tsx new file mode 100644 index 0000000000000..b2c483cbc8c97 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tags/tags.stories.tsx @@ -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 React from 'react'; +import type { Story } from '@storybook/react'; +import { TagsReadOnly } from './tags'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: TagsReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/tags', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + tags: ['Elastic', 'Cloud', 'Google Workspace', 'Log Auditing', 'Threat Detection'], + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tags/tags.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tags/tags.tsx new file mode 100644 index 0000000000000..dbb7928b5f22e --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tags/tags.tsx @@ -0,0 +1,29 @@ +/* + * 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 React from 'react'; +import { EuiDescriptionList } from '@elastic/eui'; +import * as ruleDetailsI18n from '../../../../translations'; +import type { RuleTagArray } from '../../../../../../../../../common/api/detection_engine'; +import { Tags } from '../../../../rule_about_section'; + +interface TagsReadOnlyProps { + tags: RuleTagArray; +} + +export function TagsReadOnly({ tags }: TagsReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat/threat.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat/threat.stories.tsx index 4909174dcb577..aa95633349260 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat/threat.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat/threat.stories.tsx @@ -8,8 +8,9 @@ import React from 'react'; import type { Story } from '@storybook/react'; import { FieldReadOnly } from '../../field_readonly'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { ThreatReadOnly } from './threat'; +import { mockCustomQueryRule } from '../../storybook/mocks'; export default { component: ThreatReadOnly, @@ -17,22 +18,17 @@ export default { }; interface TemplateProps { - finalDiffableRule: Partial; + finalDiffableRule: DiffableRule; } const Template: Story = (args) => { - return ( - - ); + return ; }; export const Default = Template.bind({}); Default.args = { - finalDiffableRule: { + finalDiffableRule: mockCustomQueryRule({ threat: [ { framework: 'MITRE ATT&CK', @@ -57,5 +53,5 @@ Default.args = { ], }, ], - }, + }), }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_index/threat_index.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_index/threat_index.stories.tsx index c42fa2e890c52..4f10cb8932ab1 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_index/threat_index.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_index/threat_index.stories.tsx @@ -8,8 +8,9 @@ import React from 'react'; import type { Story } from '@storybook/react'; import { FieldReadOnly } from '../../field_readonly'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { ThreatIndexReadOnly } from './threat_index'; +import { mockThreatMatchRule } from '../../storybook/mocks'; export default { component: ThreatIndexReadOnly, @@ -17,22 +18,17 @@ export default { }; interface TemplateProps { - finalDiffableRule: Partial; + finalDiffableRule: DiffableRule; } const Template: Story = (args) => { - return ( - - ); + return ; }; export const Default = Template.bind({}); Default.args = { - finalDiffableRule: { + finalDiffableRule: mockThreatMatchRule({ threat_index: ['logs-ti_*', 'logs-defend_*'], - }, + }), }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_indicator_path/threat_indicator_path.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_indicator_path/threat_indicator_path.stories.tsx index 34f0cdbcac317..be8906d76eb6b 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_indicator_path/threat_indicator_path.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_indicator_path/threat_indicator_path.stories.tsx @@ -8,8 +8,9 @@ import React from 'react'; import type { Story } from '@storybook/react'; import { FieldReadOnly } from '../../field_readonly'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { ThreatIndicatorPathReadOnly } from './threat_indicator_path'; +import { mockThreatMatchRule } from '../../storybook/mocks'; export default { component: ThreatIndicatorPathReadOnly, @@ -18,22 +19,19 @@ export default { }; interface TemplateProps { - finalDiffableRule: Partial; + finalDiffableRule: DiffableRule; } const Template: Story = (args) => { return ( - + ); }; export const Default = Template.bind({}); Default.args = { - finalDiffableRule: { + finalDiffableRule: mockThreatMatchRule({ threat_indicator_path: 'threat.indicator', - }, + }), }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_mapping/threat_mapping.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_mapping/threat_mapping.stories.tsx index 05d1aaa6cb028..4f5b8f608c4bf 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_mapping/threat_mapping.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_mapping/threat_mapping.stories.tsx @@ -8,8 +8,9 @@ import React from 'react'; import type { Story } from '@storybook/react'; import { FieldReadOnly } from '../../field_readonly'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { ThreatMappingReadOnly } from './threat_mapping'; +import { mockThreatMatchRule } from '../../storybook/mocks'; export default { component: ThreatMappingReadOnly, @@ -17,22 +18,17 @@ export default { }; interface TemplateProps { - finalDiffableRule: Partial; + finalDiffableRule: DiffableRule; } const Template: Story = (args) => { - return ( - - ); + return ; }; export const Default = Template.bind({}); Default.args = { - finalDiffableRule: { + finalDiffableRule: mockThreatMatchRule({ threat_mapping: [ { entries: [ @@ -44,5 +40,5 @@ Default.args = { ], }, ], - }, + }), }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.stories.tsx index 5b59287255bc9..28b4cd65ba78b 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.stories.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.stories.tsx @@ -8,13 +8,14 @@ import React from 'react'; import type { Story } from '@storybook/react'; import { FieldReadOnly } from '../../field_readonly'; -import type { DiffableAllFields } from '../../../../../../../../../common/api/detection_engine'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; import { ThreatQueryReadOnly } from './threat_query'; import { dataSourceWithDataView, dataSourceWithIndexPatterns, inlineKqlQuery, mockDataView, + mockThreatMatchRule, } from '../../storybook/mocks'; import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; @@ -24,17 +25,14 @@ export default { }; interface TemplateProps { - finalDiffableRule: Partial; + finalDiffableRule: DiffableRule; kibanaServicesMock?: Record; } const Template: Story = (args) => { return ( - + ); }; @@ -42,10 +40,10 @@ const Template: Story = (args) => { export const ThreatQueryWithIndexPatterns = Template.bind({}); ThreatQueryWithIndexPatterns.args = { - finalDiffableRule: { + finalDiffableRule: mockThreatMatchRule({ threat_query: inlineKqlQuery, data_source: dataSourceWithIndexPatterns, - }, + }), kibanaServicesMock: { data: { dataViews: { @@ -58,10 +56,10 @@ ThreatQueryWithIndexPatterns.args = { export const ThreatQueryWithDataView = Template.bind({}); ThreatQueryWithDataView.args = { - finalDiffableRule: { + finalDiffableRule: mockThreatMatchRule({ threat_query: inlineKqlQuery, data_source: dataSourceWithDataView, - }, + }), kibanaServicesMock: { data: { dataViews: { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.tsx index 6092fd8a0e0ce..b321213b75ad5 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_query/threat_query.tsx @@ -7,8 +7,8 @@ import React from 'react'; import type { - DiffableAllFields, InlineKqlQuery, + RuleDataSource, } from '../../../../../../../../../common/api/detection_engine'; import * as ruleDetailsI18n from '../../../../translations'; import * as descriptionStepI18n from '../../../../../../../rule_creation_ui/components/description_step/translations'; @@ -22,7 +22,7 @@ const i18nLabels = { export interface ThreatQueryReadOnlyProps { threatQuery: InlineKqlQuery; - dataSource: DiffableAllFields['data_source']; + dataSource?: RuleDataSource; } export const ThreatQueryReadOnly = ({ threatQuery, dataSource }: ThreatQueryReadOnlyProps) => { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/machine_learning_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/machine_learning_rule_field_readonly.tsx new file mode 100644 index 0000000000000..5ebc6f80b13f2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/machine_learning_rule_field_readonly.tsx @@ -0,0 +1,33 @@ +/* + * 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 React from 'react'; +import type { DiffableMachineLearningFields } from '../../../../../../../common/api/detection_engine'; +import { MachineLearningJobIdReadOnly } from './fields/machine_learning_job_id/machine_learning_job_id'; + +interface MachineLearningRuleFieldReadOnlyProps { + fieldName: keyof DiffableMachineLearningFields; + finalDiffableRule: DiffableMachineLearningFields; +} + +export function MachineLearningRuleFieldReadOnly({ + fieldName, + finalDiffableRule, +}: MachineLearningRuleFieldReadOnlyProps) { + switch (fieldName) { + case 'machine_learning_job_id': + return ( + + ); + case 'type': + return null; + default: + return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/new_terms_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/new_terms_rule_field_readonly.tsx new file mode 100644 index 0000000000000..0e2b52c71ba2b --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/new_terms_rule_field_readonly.tsx @@ -0,0 +1,38 @@ +/* + * 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 React from 'react'; +import type { DiffableNewTermsFields } from '../../../../../../../common/api/detection_engine'; +import { DataSourceReadOnly } from './fields/data_source/data_source'; +import { KqlQueryReadOnly } from './fields/kql_query'; + +interface NewTermsRuleFieldReadOnlyProps { + fieldName: keyof DiffableNewTermsFields; + finalDiffableRule: DiffableNewTermsFields; +} + +export function NewTermsRuleFieldReadOnly({ + fieldName, + finalDiffableRule, +}: NewTermsRuleFieldReadOnlyProps) { + switch (fieldName) { + case 'data_source': + return ; + case 'kql_query': + return ( + + ); + case 'type': + return null; + default: + return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/saved_query_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/saved_query_rule_field_readonly.tsx new file mode 100644 index 0000000000000..41e2e0c32108b --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/saved_query_rule_field_readonly.tsx @@ -0,0 +1,38 @@ +/* + * 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 React from 'react'; +import type { DiffableSavedQueryFields } from '../../../../../../../common/api/detection_engine'; +import { DataSourceReadOnly } from './fields/data_source/data_source'; +import { KqlQueryReadOnly } from './fields/kql_query'; + +interface SavedQueryRuleFieldReadOnlyProps { + fieldName: keyof DiffableSavedQueryFields; + finalDiffableRule: DiffableSavedQueryFields; +} + +export function SavedQueryRuleFieldReadOnly({ + fieldName, + finalDiffableRule, +}: SavedQueryRuleFieldReadOnlyProps) { + switch (fieldName) { + case 'data_source': + return ; + case 'kql_query': + return ( + + ); + case 'type': + return null; + default: + return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts index 2b21558e9b0ca..854251450809f 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/mocks.ts @@ -9,9 +9,21 @@ import type { FieldFormatsStartCommon } from '@kbn/field-formats-plugin/common'; import { DataView } from '@kbn/data-views-plugin/common'; import { DataSourceType, KqlQueryType } from '../../../../../../../../common/api/detection_engine'; import type { - DiffableAllFields, + DataSourceDataView, + DataSourceIndexPatterns, + DiffableCommonFields, + DiffableCustomQueryFields, + DiffableEqlFields, + DiffableEsqlFields, + DiffableMachineLearningFields, + DiffableRule, + DiffableSavedQueryFields, + DiffableThreatMatchFields, + InlineKqlQuery, + RuleEqlQuery, SavedKqlQuery, } from '../../../../../../../../common/api/detection_engine'; +import { DEFAULT_MAX_SIGNALS } from '../../../../../../../../common/constants'; export const filters = [ { @@ -50,7 +62,7 @@ export const savedQueryResponse = { namespaces: ['default'], }; -export const inlineKqlQuery: DiffableAllFields['kql_query'] = { +export const inlineKqlQuery: InlineKqlQuery = { type: KqlQueryType.inline_query, query: 'event.action: "user_login" and source.ip: "192.168.1.100"', language: 'kuery', @@ -62,18 +74,18 @@ export const savedKqlQuery: SavedKqlQuery = { saved_query_id: 'fake-saved-query-id', }; -export const eqlQuery: DiffableAllFields['eql_query'] = { +export const eqlQuery: RuleEqlQuery = { query: 'process where process.name == "powershell.exe" and process.args : "* -EncodedCommand *"', language: 'eql', filters, }; -export const dataSourceWithIndexPatterns: DiffableAllFields['data_source'] = { +export const dataSourceWithIndexPatterns: DataSourceIndexPatterns = { type: DataSourceType.index_patterns, index_patterns: ['logs-*'], }; -export const dataSourceWithDataView: DiffableAllFields['data_source'] = { +export const dataSourceWithDataView: DataSourceDataView = { type: DataSourceType.data_view, data_view_id: 'logs-*', }; @@ -103,3 +115,162 @@ export function mockDataView(spec: Partial = {}): DataView return dataView; } + +const commonDiffableRuleFields: DiffableCommonFields = { + rule_id: 'some-rule-id', + version: 1, + + name: 'Some Rule Name', + tags: [], + description: 'Some rule description', + severity: 'low', + severity_mapping: [], + risk_score: 1, + risk_score_mapping: [], + + references: [], + false_positives: [], + threat: [], + note: '', + setup: '', + related_integrations: [], + required_fields: [], + author: [], + license: '', + + rule_schedule: { + interval: '5m', + lookback: '360s', + }, + exceptions_list: [], + max_signals: DEFAULT_MAX_SIGNALS, +}; + +const customQueryDiffableRuleFields: DiffableCustomQueryFields = { + type: 'query', + kql_query: { + type: KqlQueryType.inline_query, + query: '*', + language: 'kuery', + filters: [], + }, +}; + +export function mockCustomQueryRule( + overrides: Partial +): DiffableRule { + return { + ...commonDiffableRuleFields, + ...customQueryDiffableRuleFields, + ...overrides, + }; +} + +const savedQueryDiffableRuleFields: DiffableSavedQueryFields = { + type: 'saved_query', + kql_query: { + type: KqlQueryType.saved_query, + saved_query_id: 'some-saved-query-id', + }, +}; + +export function mockSavedQueryRule( + overrides: Partial +): DiffableRule { + return { + ...commonDiffableRuleFields, + ...savedQueryDiffableRuleFields, + ...overrides, + }; +} + +const eqlDiffableRuleFields: DiffableEqlFields = { + type: 'eql', + eql_query: { + query: 'any where true', + language: 'eql', + filters: [], + }, +}; + +export function mockEqlRule( + overrides: Partial +): DiffableRule { + return { + ...commonDiffableRuleFields, + ...eqlDiffableRuleFields, + ...overrides, + }; +} + +const esqlDiffableRuleFields: DiffableEsqlFields = { + type: 'esql', + esql_query: { + query: 'SELECT * FROM any', + language: 'esql', + }, +}; + +export function mockEsqlRule( + overrides: Partial +): DiffableRule { + return { + ...commonDiffableRuleFields, + ...esqlDiffableRuleFields, + ...overrides, + }; +} + +const machineLearningDiffableRuleFields: DiffableMachineLearningFields = { + type: 'machine_learning', + machine_learning_job_id: 'ml-job-id-123', + anomaly_threshold: 0, +}; + +export function mockMachineLearningRule( + overrides: Partial +): DiffableRule { + return { + ...commonDiffableRuleFields, + ...machineLearningDiffableRuleFields, + ...overrides, + }; +} + +const threatMatchDiffableRuleFields: DiffableThreatMatchFields = { + type: 'threat_match', + kql_query: { + type: KqlQueryType.inline_query, + query: '*', + language: 'kuery', + filters: [], + }, + threat_query: { + type: KqlQueryType.inline_query, + query: '*', + language: 'kuery', + filters: [], + }, + threat_index: [], + threat_mapping: [ + { + entries: [ + { + field: 'abc', + type: 'mapping', + value: 'xyz', + }, + ], + }, + ], +}; + +export function mockThreatMatchRule( + overrides: Partial +): DiffableRule { + return { + ...commonDiffableRuleFields, + ...threatMatchDiffableRuleFields, + ...overrides, + }; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threat_match_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threat_match_rule_field_readonly.tsx new file mode 100644 index 0000000000000..11fd941601922 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threat_match_rule_field_readonly.tsx @@ -0,0 +1,59 @@ +/* + * 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 React from 'react'; +import type { DiffableThreatMatchFields } from '../../../../../../../common/api/detection_engine'; +import { DataSourceReadOnly } from './fields/data_source/data_source'; +import { KqlQueryReadOnly } from './fields/kql_query'; +import { ThreatIndexReadOnly } from './fields/threat_index/threat_index'; +import { ThreatIndicatorPathReadOnly } from './fields/threat_indicator_path/threat_indicator_path'; +import { ThreatMappingReadOnly } from './fields/threat_mapping/threat_mapping'; +import { ThreatQueryReadOnly } from './fields/threat_query/threat_query'; + +interface ThreatMatchRuleFieldReadOnlyProps { + fieldName: keyof DiffableThreatMatchFields; + finalDiffableRule: DiffableThreatMatchFields; +} + +export function ThreatMatchRuleFieldReadOnly({ + fieldName, + finalDiffableRule, +}: ThreatMatchRuleFieldReadOnlyProps) { + switch (fieldName) { + case 'data_source': + return ; + case 'kql_query': + return ( + + ); + case 'threat_index': + return ; + case 'threat_indicator_path': + return ( + + ); + case 'threat_mapping': + return ; + case 'threat_query': + return ( + + ); + case 'type': + return null; + default: + return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + } +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threshold_rule_field_readonly.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threshold_rule_field_readonly.tsx new file mode 100644 index 0000000000000..da7d3984d7ccb --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/threshold_rule_field_readonly.tsx @@ -0,0 +1,38 @@ +/* + * 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 React from 'react'; +import type { DiffableThresholdFields } from '../../../../../../../common/api/detection_engine'; +import { DataSourceReadOnly } from './fields/data_source/data_source'; +import { KqlQueryReadOnly } from './fields/kql_query'; + +interface ThresholdRuleFieldReadOnlyProps { + fieldName: keyof DiffableThresholdFields; + finalDiffableRule: DiffableThresholdFields; +} + +export function ThresholdRuleFieldReadOnly({ + fieldName, + finalDiffableRule, +}: ThresholdRuleFieldReadOnlyProps) { + switch (fieldName) { + case 'data_source': + return ; + case 'kql_query': + return ( + + ); + case 'type': + return null; + default: + return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + } +}