From 1d17d2fe9139de92effc1a44b51d8db1c4eadd99 Mon Sep 17 00:00:00 2001 From: Nikita Indik Date: Tue, 24 Sep 2024 10:04:38 +0200 Subject: [PATCH] [Security Solution] ThreeWayDiff UI: Add remaining field components for `FieldReadOnly` (#193261) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Partially addresses: https://github.com/elastic/kibana/issues/171520** **Is a follow-up PR to: https://github.com/elastic/kibana/pull/192342** This is the 3rd of the 3 PRs for `FieldReadOnly`. - The 1st [PR](https://github.com/elastic/kibana/pull/191499) added the `FieldReadOnly` and a bunch of field components. - The 2nd [PR](https://github.com/elastic/kibana/pull/192342) moved away from using `DiffableAllFields` type in favour of `DiffableRule` and split the large `FieldReadOnly` component into smaller ones for readability. - This (3rd) PR adds the remaining field components. ## Summary This PR adds field components for `FieldReadOnly`. Field components display a read-only view of a particular `DiffableRule` field, similar to how fields are shown on the Rule Details page. `FieldReadOnly` and field components will be displayed in the right side of the new Diff tab of the Upgrade flyout (see it on the [Miro board](https://miro.com/app/board/uXjVK0gqjjQ=/?moveToWidget=3458764594148126123&cot=14)). They will let the user see how an upgraded version of a rule will look like in a user-friendly way. ### Running `FinalReadOnly` and its field components are not yet integrated into the flyout, but you can view components in Storybook. 1. Run Storybook: `yarn storybook security_solution` 2. Go to `http://localhost:9001` in browser. Scherm­afbeelding 2024-09-03 om 13 05 11 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Maxim Palenov (cherry picked from commit b78b6337970b2e7332266cd0e181e14d26c3ed45) --- .../rule_details/json_diff/json_diff.test.tsx | 2 +- .../rule_details/rule_about_section.tsx | 20 ++--- .../rule_details/rule_definition_section.tsx | 18 ++--- .../rule_details/rule_schedule_section.tsx | 25 ++++-- .../common_rule_field_readonly.tsx | 50 ++++++++---- .../custom_query_rule_field_readonly.tsx | 14 +++- .../eql_rule_field_readonly.tsx | 27 ++++++- .../esql_rule_field_readonly.tsx | 14 +++- .../alert_suppression.stories.tsx | 44 ++++++++++ .../alert_suppression/alert_suppression.tsx | 81 +++++++++++++++++++ .../anomaly_threshold.stories.tsx | 35 ++++++++ .../anomaly_threshold/anomaly_threshold.tsx | 29 +++++++ .../fields/author/author.stories.tsx | 34 ++++++++ .../final_readonly/fields/author/author.tsx | 29 +++++++ .../building_block/building_block.stories.tsx | 36 +++++++++ .../fields/building_block/building_block.tsx | 24 ++++++ .../data_source/data_source.stories.tsx | 6 +- .../fields/eql_query/eql_query.stories.tsx | 8 +- .../event_category_override.stories.tsx | 37 +++++++++ .../event_category_override.tsx | 42 ++++++++++ .../false_positives.stories.tsx | 37 +++++++++ .../false_positives/false_positives.tsx | 29 +++++++ .../history_window_start.stories.tsx | 37 +++++++++ .../history_window_start.tsx | 31 +++++++ .../investigation_fields.stories.tsx | 39 +++++++++ .../investigation_fields.tsx | 37 +++++++++ .../fields/kql_query/kql_query.stories.tsx | 14 ++-- .../fields/license/license.stories.tsx | 34 ++++++++ .../final_readonly/fields/license/license.tsx | 29 +++++++ .../max_signals/max_signals.stories.tsx | 34 ++++++++ .../fields/max_signals/max_signals.tsx | 29 +++++++ .../new_terms_fields.stories.tsx | 35 ++++++++ .../new_terms_fields/new_terms_fields.tsx | 29 +++++++ .../fields/note/note.stories.tsx | 34 ++++++++ .../final_readonly/fields/note/note.tsx | 37 +++++++++ .../fields/note/translations.ts | 15 ++++ .../fields/references/references.stories.tsx | 38 +++++++++ .../fields/references/references.tsx | 29 +++++++ .../fields/risk_score/risk_score.stories.tsx | 34 ++++++++ .../fields/risk_score/risk_score.tsx | 29 +++++++ .../rule_name_override.stories.tsx | 39 +++++++++ .../rule_name_override/rule_name_override.tsx | 33 ++++++++ .../rule_schedule/rule_schedule.stories.tsx | 37 +++++++++ .../fields/rule_schedule/rule_schedule.tsx | 38 +++++++++ .../fields/setup/setup.stories.tsx | 35 ++++++++ .../final_readonly/fields/setup/setup.tsx | 37 +++++++++ .../fields/severity/severity.stories.tsx | 34 ++++++++ .../fields/severity/severity.tsx | 29 +++++++ .../threat_language.stories.tsx | 34 ++++++++ .../threat_language/threat_language.tsx | 33 ++++++++ .../threat_query/threat_query.stories.tsx | 8 +- .../fields/threshold/threshold.stories.tsx | 38 +++++++++ .../fields/threshold/threshold.tsx | 29 +++++++ .../tiebreaker_field.stories.tsx | 35 ++++++++ .../tiebreaker_field/tiebreaker_field.tsx | 40 +++++++++ .../timeline_template.stories.tsx | 38 +++++++++ .../timeline_template/timeline_template.tsx | 33 ++++++++ .../timestamp_field.stories.tsx | 34 ++++++++ .../timestamp_field/timestamp_field.tsx | 40 +++++++++ .../timestamp_override.stories.tsx | 40 +++++++++ .../timestamp_override/timestamp_override.tsx | 33 ++++++++ .../fields/type/type.stories.tsx | 34 ++++++++ .../final_readonly/fields/type/type.tsx | 29 +++++++ .../machine_learning_rule_field_readonly.tsx | 17 +++- .../new_terms_rule_field_readonly.tsx | 22 ++++- .../saved_query_rule_field_readonly.tsx | 14 +++- .../final_readonly/storybook/mocks.ts | 48 +++++++++++ .../three_way_diff_storybook_providers.tsx | 19 ++++- .../threat_match_rule_field_readonly.tsx | 17 +++- .../threshold_rule_field_readonly.tsx | 17 +++- .../pages/detection_engine/rules/helpers.tsx | 28 ++++--- 71 files changed, 2079 insertions(+), 88 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/translations.ts create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.tsx diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/json_diff/json_diff.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/json_diff/json_diff.test.tsx index 8e9c465d265b8..2a769e4be87d4 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/json_diff/json_diff.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/json_diff/json_diff.test.tsx @@ -19,7 +19,7 @@ import { COLORS } from './constants'; /* Finds an element with a text content that exactly matches the passed argument. - Handly because React Testing Library's doesn't provide an easy way to search by + Handy because React Testing Library's doesn't provide an easy way to search by text if the text is split into multiple DOM elements. */ function findChildByTextContent(parent: Element, textContent: string): HTMLElement { 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 1d2e93df8e7f7..396811892610b 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 @@ -72,11 +72,11 @@ interface AuthorProps { author: string[]; } -const Author = ({ author }: AuthorProps) => ( +export const Author = ({ author }: AuthorProps) => ( ); -const BuildingBlock = () => ( +export const BuildingBlock = () => ( {i18n.BUILDING_BLOCK_FIELD_DESCRIPTION} @@ -124,7 +124,7 @@ interface RiskScoreProps { riskScore: number; } -const RiskScore = ({ riskScore }: RiskScoreProps) => ( +export const RiskScore = ({ riskScore }: RiskScoreProps) => ( {riskScore} @@ -157,7 +157,7 @@ interface ReferencesProps { references: string[]; } -const References = ({ references }: ReferencesProps) => ( +export const References = ({ references }: ReferencesProps) => (
    {references @@ -173,7 +173,7 @@ const References = ({ references }: ReferencesProps) => ( ); -const FalsePositives = ({ falsePositives }: { falsePositives: string[] }) => ( +export const FalsePositives = ({ falsePositives }: { falsePositives: string[] }) => (
      {falsePositives.map((falsePositivesItem) => ( @@ -192,7 +192,7 @@ interface InvestigationFieldsProps { investigationFields: string[]; } -const InvestigationFields = ({ investigationFields }: InvestigationFieldsProps) => ( +export const InvestigationFields = ({ investigationFields }: InvestigationFieldsProps) => ( ); @@ -200,7 +200,7 @@ interface LicenseProps { license: string; } -const License = ({ license }: LicenseProps) => ( +export const License = ({ license }: LicenseProps) => ( {license} @@ -210,7 +210,7 @@ interface RuleNameOverrideProps { ruleNameOverride: string; } -const RuleNameOverride = ({ ruleNameOverride }: RuleNameOverrideProps) => ( +export const RuleNameOverride = ({ ruleNameOverride }: RuleNameOverrideProps) => ( {ruleNameOverride} @@ -236,7 +236,7 @@ interface TimestampOverrideProps { timestampOverride: string; } -const TimestampOverride = ({ timestampOverride }: TimestampOverrideProps) => ( +export const TimestampOverride = ({ timestampOverride }: TimestampOverrideProps) => ( {timestampOverride} @@ -246,7 +246,7 @@ interface MaxSignalsProps { maxSignals: number; } -const MaxSignals = ({ maxSignals }: MaxSignalsProps) => ( +export const MaxSignals = ({ maxSignals }: MaxSignalsProps) => ( {maxSignals} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_definition_section.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_definition_section.tsx index e0b0431138508..184633d813675 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_definition_section.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_definition_section.tsx @@ -179,7 +179,7 @@ interface ThresholdProps { threshold: ThresholdType; } -const Threshold = ({ threshold }: ThresholdProps) => ( +export const Threshold = ({ threshold }: ThresholdProps) => (
      {isEmpty(threshold.field[0]) ? `${descriptionStepI18n.THRESHOLD_RESULTS_ALL} >= ${threshold.value}` @@ -193,7 +193,7 @@ interface AnomalyThresholdProps { anomalyThreshold: number; } -const AnomalyThreshold = ({ anomalyThreshold }: AnomalyThresholdProps) => ( +export const AnomalyThreshold = ({ anomalyThreshold }: AnomalyThresholdProps) => ( {anomalyThreshold} @@ -258,7 +258,7 @@ interface RuleTypeProps { type: Type; } -const RuleType = ({ type }: RuleTypeProps) => ( +export const RuleType = ({ type }: RuleTypeProps) => ( {getRuleTypeDescription(type)} ); @@ -298,7 +298,7 @@ interface TimelineTitleProps { timelineTitle: string; } -const TimelineTitle = ({ timelineTitle }: TimelineTitleProps) => ( +export const TimelineTitle = ({ timelineTitle }: TimelineTitleProps) => ( {timelineTitle} @@ -354,7 +354,7 @@ interface SuppressAlertsByFieldProps { fields: string[]; } -const SuppressAlertsByField = ({ fields }: SuppressAlertsByFieldProps) => ( +export const SuppressAlertsByField = ({ fields }: SuppressAlertsByFieldProps) => ( ); @@ -362,7 +362,7 @@ interface SuppressAlertsDurationProps { duration?: Duration; } -const SuppressAlertsDuration = ({ duration }: SuppressAlertsDurationProps) => { +export const SuppressAlertsDuration = ({ duration }: SuppressAlertsDurationProps) => { const durationDescription = duration ? `${duration.value}${duration.unit}` : descriptionStepI18n.ALERT_SUPPRESSION_PER_RULE_EXECUTION; @@ -378,7 +378,7 @@ interface MissingFieldsStrategyProps { missingFieldsStrategy?: AlertSuppressionMissingFieldsStrategy; } -const MissingFieldsStrategy = ({ missingFieldsStrategy }: MissingFieldsStrategyProps) => { +export const MissingFieldsStrategy = ({ missingFieldsStrategy }: MissingFieldsStrategyProps) => { const missingFieldsDescription = missingFieldsStrategy === AlertSuppressionMissingFieldsStrategyEnum.suppress ? descriptionStepI18n.ALERT_SUPPRESSION_SUPPRESS_ON_MISSING_FIELDS @@ -395,7 +395,7 @@ interface NewTermsFieldsProps { newTermsFields: string[]; } -const NewTermsFields = ({ newTermsFields }: NewTermsFieldsProps) => ( +export const NewTermsFields = ({ newTermsFields }: NewTermsFieldsProps) => ( ); @@ -403,7 +403,7 @@ interface HistoryWindowSizeProps { historyWindowStart?: string; } -const HistoryWindowSize = ({ historyWindowStart }: HistoryWindowSizeProps) => { +export const HistoryWindowSize = ({ historyWindowStart }: HistoryWindowSizeProps) => { const size = historyWindowStart ? convertHistoryStartToSize(historyWindowStart) : '7d'; return ( diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_schedule_section.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_schedule_section.tsx index 7d7579521c82d..5ed99e4328136 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_schedule_section.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_schedule_section.tsx @@ -14,14 +14,26 @@ import { getHumanizedDuration } from '../../../../detections/pages/detection_eng import { DEFAULT_DESCRIPTION_LIST_COLUMN_WIDTHS } from './constants'; import * as i18n from './translations'; +interface AccessibleTimeValueProps { + timeValue: string; + 'data-test-subj'?: string; +} + +export const AccessibleTimeValue = ({ + timeValue, + 'data-test-subj': dataTestSubj, +}: AccessibleTimeValueProps) => ( + + + +); + interface IntervalProps { interval: string; } const Interval = ({ interval }: IntervalProps) => ( - - - + ); interface FromProps { @@ -30,9 +42,10 @@ interface FromProps { } const From = ({ from, interval }: FromProps) => ( - - - + ); export interface RuleScheduleSectionProps extends React.ComponentProps { 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 index 35bde351bbeb6..9471a17b216b3 100644 --- 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 @@ -19,6 +19,21 @@ import { NameReadOnly } from './fields/name/name'; import { TagsReadOnly } from './fields/tags/tags'; import { DescriptionReadOnly } from './fields/description/description'; import { assertUnreachable } from '../../../../../../../common/utility_types'; +import { AuthorReadOnly } from './fields/author/author'; +import { BuildingBlockReadOnly } from './fields/building_block/building_block'; +import { InvestigationFieldsReadOnly } from './fields/investigation_fields/investigation_fields'; +import { FalsePositivesReadOnly } from './fields/false_positives/false_positives'; +import { LicenseReadOnly } from './fields/license/license'; +import { MaxSignalsReadOnly } from './fields/max_signals/max_signals'; +import { NoteReadOnly } from './fields/note/note'; +import { RuleScheduleReadOnly } from './fields/rule_schedule/rule_schedule'; +import { ReferencesReadOnly } from './fields/references/references'; +import { RiskScoreReadOnly } from './fields/risk_score/risk_score'; +import { RuleNameOverrideReadOnly } from './fields/rule_name_override/rule_name_override'; +import { SetupReadOnly } from './fields/setup/setup'; +import { SeverityReadOnly } from './fields/severity/severity'; +import { TimestampOverrideReadOnly } from './fields/timestamp_override/timestamp_override'; +import { TimelineTemplateReadOnly } from './fields/timeline_template/timeline_template'; interface CommonRuleFieldReadOnlyProps { fieldName: keyof DiffableCommonFields; @@ -32,25 +47,28 @@ export function CommonRuleFieldReadOnly({ }: CommonRuleFieldReadOnlyProps) { switch (fieldName) { case 'author': - return null; + return ; case 'building_block': - return null; + return ; case 'description': return ; case 'exceptions_list': + /* Exceptions are not used in prebuilt rules */ return null; case 'investigation_fields': - return null; + return ( + + ); case 'false_positives': - return null; + return ; case 'license': - return null; + return ; case 'max_signals': - return null; + return ; case 'name': return ; case 'note': - return null; + return ; case 'related_integrations': return ( @@ -60,7 +78,7 @@ export function CommonRuleFieldReadOnly({ case 'risk_score_mapping': return ; case 'rule_schedule': - return null; + return ; case 'severity_mapping': return ; case 'tags': @@ -68,22 +86,24 @@ export function CommonRuleFieldReadOnly({ case 'threat': return ; case 'references': - return null; + return ; case 'risk_score': - return null; + return ; case 'rule_id': + /* Rule ID is not displayed in the UI */ return null; case 'rule_name_override': - return null; + return ; case 'setup': - return null; + return ; case 'severity': - return null; + return ; case 'timestamp_override': - return null; + return ; case 'timeline_template': - return null; + return ; case 'version': + /* Version is not displayed in the UI */ 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 index 3d22d268438c4..da435b8092cd6 100644 --- 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 @@ -9,6 +9,9 @@ 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'; +import { assertUnreachable } from '../../../../../../../common/utility_types'; +import { TypeReadOnly } from './fields/type/type'; +import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression'; interface CustomQueryRuleFieldReadOnlyProps { fieldName: keyof DiffableCustomQueryFields; @@ -20,6 +23,13 @@ export function CustomQueryRuleFieldReadOnly({ finalDiffableRule, }: CustomQueryRuleFieldReadOnlyProps) { switch (fieldName) { + case 'alert_suppression': + return ( + + ); case 'data_source': return ; case 'kql_query': @@ -30,7 +40,9 @@ export function CustomQueryRuleFieldReadOnly({ ruleType={finalDiffableRule.type} /> ); + case 'type': + return ; default: - return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + return assertUnreachable(fieldName); } } 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 index 126775965724b..b72fce91f198c 100644 --- 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 @@ -9,6 +9,12 @@ 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'; +import { TypeReadOnly } from './fields/type/type'; +import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression'; +import { assertUnreachable } from '../../../../../../../common/utility_types'; +import { EventCategoryOverrideReadOnly } from './fields/event_category_override/event_category_override'; +import { TimestampFieldReadOnly } from './fields/timestamp_field/timestamp_field'; +import { TiebreakerFieldReadOnly } from './fields/tiebreaker_field/tiebreaker_field'; interface EqlRuleFieldReadOnlyProps { fieldName: keyof DiffableEqlFields; @@ -17,6 +23,13 @@ interface EqlRuleFieldReadOnlyProps { export function EqlRuleFieldReadOnly({ fieldName, finalDiffableRule }: EqlRuleFieldReadOnlyProps) { switch (fieldName) { + case 'alert_suppression': + return ( + + ); case 'data_source': return ; case 'eql_query': @@ -26,9 +39,19 @@ export function EqlRuleFieldReadOnly({ fieldName, finalDiffableRule }: EqlRuleFi dataSource={finalDiffableRule.data_source} /> ); + case 'event_category_override': + return ( + + ); + case 'tiebreaker_field': + return ; + case 'timestamp_field': + return ; case 'type': - return null; + return ; default: - return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + return assertUnreachable(fieldName); } } 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 index 755ad6b1b4789..04280ebaacc5b 100644 --- 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 @@ -8,6 +8,9 @@ import React from 'react'; import type { DiffableEsqlFields } from '../../../../../../../common/api/detection_engine'; import { EsqlQueryReadOnly } from './fields/esql_query/esql_query'; +import { TypeReadOnly } from './fields/type/type'; +import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression'; +import { assertUnreachable } from '../../../../../../../common/utility_types'; interface EsqlRuleFieldReadOnlyProps { fieldName: keyof DiffableEsqlFields; @@ -19,11 +22,18 @@ export function EsqlRuleFieldReadOnly({ finalDiffableRule, }: EsqlRuleFieldReadOnlyProps) { switch (fieldName) { + case 'alert_suppression': + return ( + + ); case 'esql_query': return ; case 'type': - return null; + return ; default: - return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + return assertUnreachable(fieldName); } } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.stories.tsx new file mode 100644 index 0000000000000..4f6739a3af481 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.stories.tsx @@ -0,0 +1,44 @@ +/* + * 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 { AlertSuppressionReadOnly } from './alert_suppression'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; +import { ThreeWayDiffStorybookProviders } from '../../storybook/three_way_diff_storybook_providers'; + +export default { + component: AlertSuppressionReadOnly, + title: + 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/alert_suppression', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ( + + + + ); +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + alert_suppression: { + group_by: ['host.name'], + duration: { value: 5, unit: 'm' }, + missing_fields_strategy: 'suppress', + }, + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.tsx new file mode 100644 index 0000000000000..8c15347bc6d90 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/alert_suppression/alert_suppression.tsx @@ -0,0 +1,81 @@ +/* + * 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 { + AlertSuppression, + DiffableRuleTypes, + ThresholdAlertSuppression, +} from '../../../../../../../../../common/api/detection_engine'; +import { AlertSuppressionLabel } from '../../../../../../../rule_creation_ui/components/description_step/alert_suppression_label'; +import { + MissingFieldsStrategy, + SuppressAlertsByField, + SuppressAlertsDuration, +} from '../../../../rule_definition_section'; + +interface AlertSuppressionReadOnlyProps { + alertSuppression?: AlertSuppression | ThresholdAlertSuppression; + ruleType: DiffableRuleTypes; +} + +export function AlertSuppressionReadOnly({ + alertSuppression, + ruleType, +}: AlertSuppressionReadOnlyProps) { + if (!alertSuppression) { + return null; + } + + const listItems = []; + + if ('group_by' in alertSuppression) { + listItems.push({ + title: ( + + ), + description: , + }); + } + + if ('duration' in alertSuppression) { + listItems.push({ + title: ( + + + + ), + description: , + }); + } + + if ('missing_fields_strategy' in alertSuppression) { + listItems.push({ + title: ( + + + + ), + description: ( + + ), + }); + } + + return ; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.stories.tsx new file mode 100644 index 0000000000000..8203e015d11db --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.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 { AnomalyThresholdReadOnly } from './anomaly_threshold'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockMachineLearningRule } from '../../storybook/mocks'; + +export default { + component: AnomalyThresholdReadOnly, + title: + 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/anomaly_threshold', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockMachineLearningRule({ + anomaly_threshold: 50, + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.tsx new file mode 100644 index 0000000000000..20b9026c2a8ae --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/anomaly_threshold/anomaly_threshold.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 { AnomalyThreshold as AnomalyThresholdType } from '../../../../../../../../../common/api/detection_engine'; +import { AnomalyThreshold } from '../../../../rule_definition_section'; + +interface TagsReadOnlyProps { + anomalyThreshold: AnomalyThresholdType; +} + +export function AnomalyThresholdReadOnly({ anomalyThreshold }: TagsReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.stories.tsx new file mode 100644 index 0000000000000..2700517c1c3ec --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.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 { AuthorReadOnly } from './author'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: AuthorReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/author', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + author: ['Elastic', 'John Doe'], + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.tsx new file mode 100644 index 0000000000000..c284275bd4db4 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/author/author.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 { RuleAuthorArray } from '../../../../../../../../../common/api/detection_engine'; +import { Author } from '../../../../rule_about_section'; + +interface AuthorReadOnlyProps { + author: RuleAuthorArray; +} + +export function AuthorReadOnly({ author }: AuthorReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.stories.tsx new file mode 100644 index 0000000000000..f927b753c17ab --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.stories.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 { Story } from '@storybook/react'; +import { BuildingBlockReadOnly } from './building_block'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: BuildingBlockReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/building_block', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + building_block: { + type: 'default', + }, + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.tsx new file mode 100644 index 0000000000000..84edd7932a2d7 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/building_block/building_block.tsx @@ -0,0 +1,24 @@ +/* + * 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 { BuildingBlock } from '../../../../rule_about_section'; + +export function BuildingBlockReadOnly() { + return ( + , + }, + ]} + /> + ); +} 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 9deebf794c241..091a874385156 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 @@ -24,12 +24,12 @@ export default { interface TemplateProps { finalDiffableRule: DiffableRule; - kibanaServicesMock?: Record; + kibanaServicesOverrides?: Record; } const Template: Story = (args) => { return ( - + ); @@ -49,7 +49,7 @@ DataSourceWithDataView.args = { finalDiffableRule: mockCustomQueryRule({ data_source: dataSourceWithDataView, }), - kibanaServicesMock: { + kibanaServicesOverrides: { data: { dataViews: { get: async () => mockDataView(), 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 af835c5a92779..84ea98047bcee 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 @@ -26,12 +26,12 @@ export default { interface TemplateProps { finalDiffableRule: DiffableRule; - kibanaServicesMock?: Record; + kibanaServicesOverrides?: Record; } const Template: Story = (args) => { return ( - + ); @@ -44,7 +44,7 @@ EqlQueryWithIndexPatterns.args = { eql_query: eqlQuery, data_source: dataSourceWithIndexPatterns, }), - kibanaServicesMock: { + kibanaServicesOverrides: { data: { dataViews: { create: async () => mockDataView(), @@ -60,7 +60,7 @@ EqlQueryWithDataView.args = { eql_query: eqlQuery, data_source: dataSourceWithDataView, }), - kibanaServicesMock: { + kibanaServicesOverrides: { data: { dataViews: { get: async () => mockDataView(), diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.stories.tsx new file mode 100644 index 0000000000000..1eb29ef1084d9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.stories.tsx @@ -0,0 +1,37 @@ +/* + * 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 { EventCategoryOverrideReadOnly } from './event_category_override'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockEqlRule } from '../../storybook/mocks'; + +export default { + component: EventCategoryOverrideReadOnly, + title: + 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/event_category_override', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ( + + ); +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockEqlRule({ + event_category_override: 'event.action', + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.tsx new file mode 100644 index 0000000000000..910e639049f96 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/event_category_override/event_category_override.tsx @@ -0,0 +1,42 @@ +/* + * 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, EuiText } from '@elastic/eui'; +import * as descriptionStepI18n from '../../../../../../../rule_creation_ui/components/description_step/translations'; +import type { EventCategoryOverride as EventCategoryOverrideType } from '../../../../../../../../../common/api/detection_engine'; + +interface EventCategoryOverrideReadOnlyProps { + eventCategoryOverride?: EventCategoryOverrideType; +} + +export function EventCategoryOverrideReadOnly({ + eventCategoryOverride, +}: EventCategoryOverrideReadOnlyProps) { + if (!eventCategoryOverride) { + return null; + } + + return ( + , + }, + ]} + /> + ); +} + +interface EventCategoryOverrideProps { + eventCategoryOverride: EventCategoryOverrideType; +} + +function EventCategoryOverride({ eventCategoryOverride }: EventCategoryOverrideProps) { + return {eventCategoryOverride}; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.stories.tsx new file mode 100644 index 0000000000000..60d8a34616652 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.stories.tsx @@ -0,0 +1,37 @@ +/* + * 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 { FalsePositivesReadOnly } from './false_positives'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: FalsePositivesReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/false_positives', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + false_positives: [ + 'WAF rules or rule groups may be deleted by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Rule deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule.', + 'Uncommon user command activity can be due to an engineer logging onto a server instance in order to perform manual troubleshooting or reconfiguration.', + ], + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.tsx new file mode 100644 index 0000000000000..f026609b6c850 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/false_positives/false_positives.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 { RuleFalsePositiveArray } from '../../../../../../../../../common/api/detection_engine'; +import { FalsePositives } from '../../../../rule_about_section'; + +interface FalsePositivesReadOnlyProps { + falsePositives: RuleFalsePositiveArray; +} + +export function FalsePositivesReadOnly({ falsePositives }: FalsePositivesReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.stories.tsx new file mode 100644 index 0000000000000..c84868e97ee0c --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.stories.tsx @@ -0,0 +1,37 @@ +/* + * 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 { HistoryWindowStartReadOnly } from './history_window_start'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockNewTermsRule } from '../../storybook/mocks'; + +export default { + component: HistoryWindowStartReadOnly, + title: + 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/history_window_start', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ( + + ); +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockNewTermsRule({ + history_window_start: 'now-14d', + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.tsx new file mode 100644 index 0000000000000..c6bd8ebf7b972 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/history_window_start/history_window_start.tsx @@ -0,0 +1,31 @@ +/* + * 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 { HistoryWindowStart as HistoryWindowStartType } from '../../../../../../../../../common/api/detection_engine'; +import { HistoryWindowSize } from '../../../../rule_definition_section'; + +interface HistoryWindowStartReadOnlyProps { + historyWindowStart: HistoryWindowStartType; +} + +export function HistoryWindowStartReadOnly({ + historyWindowStart, +}: HistoryWindowStartReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.stories.tsx new file mode 100644 index 0000000000000..e73b01a719f8a --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.stories.tsx @@ -0,0 +1,39 @@ +/* + * 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 { InvestigationFieldsReadOnly } from './investigation_fields'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: InvestigationFieldsReadOnly, + title: + 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/investigation_fields', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ( + + ); +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + investigation_fields: { + field_names: ['host.name', 'source.ip'], + }, + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.tsx new file mode 100644 index 0000000000000..b567b32ada533 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/investigation_fields/investigation_fields.tsx @@ -0,0 +1,37 @@ +/* + * 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 { InvestigationFields } from '../../../../../../../../../common/api/detection_engine'; +import { InvestigationFields as InvestigationFieldsComponent } from '../../../../rule_about_section'; + +interface InvestigationFieldsReadOnlyProps { + investigationFields?: InvestigationFields; +} + +export function InvestigationFieldsReadOnly({ + investigationFields, +}: InvestigationFieldsReadOnlyProps) { + if (!investigationFields || !investigationFields.field_names.length) { + return null; + } + + return ( + + ), + }, + ]} + /> + ); +} 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 2b4844ceac5d5..4fd102fc0627f 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 @@ -28,12 +28,12 @@ export default { interface TemplateProps { finalDiffableRule: DiffableRule; - kibanaServicesMock?: Record; + kibanaServicesOverrides?: Record; } const Template: Story = (args) => { return ( - + ); @@ -46,7 +46,7 @@ InlineKqlQueryWithIndexPatterns.args = { kql_query: inlineKqlQuery, data_source: dataSourceWithIndexPatterns, }), - kibanaServicesMock: { + kibanaServicesOverrides: { data: { dataViews: { create: async () => mockDataView(), @@ -62,7 +62,7 @@ InlineKqlQueryWithDataView.args = { kql_query: inlineKqlQuery, data_source: dataSourceWithDataView, }), - kibanaServicesMock: { + kibanaServicesOverrides: { data: { dataViews: { get: async () => mockDataView(), @@ -81,7 +81,7 @@ InlineKqlQueryWithoutDataSource.args = { finalDiffableRule: mockCustomQueryRule({ kql_query: inlineKqlQuery, }), - kibanaServicesMock: { + kibanaServicesOverrides: { data: { dataViews: { create: async () => mockDataView(), @@ -98,7 +98,7 @@ SavedKqlQueryWithIndexPatterns.args = { data_source: dataSourceWithIndexPatterns, type: 'saved_query', }), - kibanaServicesMock: { + kibanaServicesOverrides: { data: { dataViews: { create: async () => mockDataView(), @@ -118,7 +118,7 @@ SavedKqlQueryWithDataView.args = { data_source: dataSourceWithDataView, type: 'saved_query', }), - kibanaServicesMock: { + kibanaServicesOverrides: { data: { dataViews: { get: async () => mockDataView(), diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.stories.tsx new file mode 100644 index 0000000000000..044564acd91d8 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.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 { LicenseReadOnly } from './license'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: LicenseReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/license', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + license: 'Elastic License 2.0', + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.tsx new file mode 100644 index 0000000000000..18032f66ab81d --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/license/license.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 { RuleLicense } from '../../../../../../../../../common/api/detection_engine'; +import { License } from '../../../../rule_about_section'; + +interface LicenseReadOnlyProps { + license: RuleLicense; +} + +export function LicenseReadOnly({ license }: LicenseReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.stories.tsx new file mode 100644 index 0000000000000..d6f369ff47ce6 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.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 { MaxSignalsReadOnly } from './max_signals'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: MaxSignalsReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/max_signals', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + max_signals: 100, + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.tsx new file mode 100644 index 0000000000000..d0bda317a416a --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/max_signals/max_signals.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 { MaxSignals as MaxSignalsType } from '../../../../../../../../../common/api/detection_engine'; +import { MaxSignals } from '../../../../rule_about_section'; + +interface MaxSignalsReadOnlyProps { + maxSignals: MaxSignalsType; +} + +export function MaxSignalsReadOnly({ maxSignals }: MaxSignalsReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.stories.tsx new file mode 100644 index 0000000000000..8f77a747fa06c --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.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 { NewTermsFieldsReadOnly } from './new_terms_fields'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockNewTermsRule } from '../../storybook/mocks'; + +export default { + component: NewTermsFieldsReadOnly, + title: + 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/new_terms_fields', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockNewTermsRule({ + new_terms_fields: ['user.name', 'source.ip'], + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.tsx new file mode 100644 index 0000000000000..b77f7b0736482 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/new_terms_fields/new_terms_fields.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 { NewTermsFields as NewTermsFieldsType } from '../../../../../../../../../common/api/detection_engine'; +import { NewTermsFields } from '../../../../rule_definition_section'; + +interface NewTermsFieldsReadOnlyProps { + newTermsFields: NewTermsFieldsType; +} + +export function NewTermsFieldsReadOnly({ newTermsFields }: NewTermsFieldsReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.stories.tsx new file mode 100644 index 0000000000000..501faeb1cfbad --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.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 { NoteReadOnly } from './note'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: NoteReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/note', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + note: '## Triage and analysis\n\n### Investigating Unusual Network Activity\nDetection alerts from this rule indicate the presence of network activity from a Linux process for which network activity is rare and unusual. Here are some possible avenues of investigation:\n- Consider the IP addresses and ports. Are these used by normal but infrequent network workflows? Are they expected or unexpected?\n- If the destination IP address is remote or external, does it associate with an expected domain, organization or geography? Note: avoid interacting directly with suspected malicious IP addresses.\n- Consider the user as identified by the username field. Is this network activity part of an expected workflow for the user who ran the program?\n- Examine the history of execution. If this process only manifested recently, it might be part of a new software package. If it has a consistent cadence (for example if it runs monthly or quarterly), it might be part of a monthly or quarterly business or maintenance process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.', + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.tsx new file mode 100644 index 0000000000000..37184df117110 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/note.tsx @@ -0,0 +1,37 @@ +/* + * 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 i18n from './translations'; +import type { InvestigationGuide } from '../../../../../../../../../common/api/detection_engine'; +import { MarkdownRenderer } from '../../../../../../../../common/components/markdown_editor'; + +interface NoteReadOnlyProps { + note: InvestigationGuide; +} + +export function NoteReadOnly({ note }: NoteReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} + +interface NoteProps { + note: InvestigationGuide; +} + +function Note({ note }: NoteProps) { + return {note}; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/translations.ts new file mode 100644 index 0000000000000..7a36a7d117d8d --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/note/translations.ts @@ -0,0 +1,15 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export const NOTE_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.fieldReadOnly.noteLabel', + { + defaultMessage: 'Investigation guide', + } +); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.stories.tsx new file mode 100644 index 0000000000000..561d5b36cf4f3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.stories.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 { Story } from '@storybook/react'; +import { ReferencesReadOnly } from './references'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: ReferencesReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/references', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + references: [ + 'https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html', + 'https://docs.elastic.co/en/integrations/beaconing', + 'https://www.elastic.co/security-labs/identifying-beaconing-malware-using-elastic', + ], + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.tsx new file mode 100644 index 0000000000000..c98c5a53bb2e8 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/references/references.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 { RuleReferenceArray } from '../../../../../../../../../common/api/detection_engine'; +import { References } from '../../../../rule_about_section'; + +interface ReferencesReadOnlyProps { + references: RuleReferenceArray; +} + +export function ReferencesReadOnly({ references }: ReferencesReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.stories.tsx new file mode 100644 index 0000000000000..c0be0fb6190f6 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.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 { RiskScoreReadOnly } from './risk_score'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: RiskScoreReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/risk_score', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + risk_score: 96, + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.tsx new file mode 100644 index 0000000000000..ef6ddbd7d8217 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/risk_score/risk_score.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 { RiskScore as RiskScoreType } from '../../../../../../../../../common/api/detection_engine'; +import { RiskScore } from '../../../../rule_about_section'; + +interface RiskScoreReadOnlyProps { + riskScore: RiskScoreType; +} + +export function RiskScoreReadOnly({ riskScore }: RiskScoreReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.stories.tsx new file mode 100644 index 0000000000000..fa46e313fd664 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.stories.tsx @@ -0,0 +1,39 @@ +/* + * 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 { RuleNameOverrideReadOnly } from './rule_name_override'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: RuleNameOverrideReadOnly, + title: + 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/rule_name_override', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ( + + ); +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + rule_name_override: { + field_name: 'event.action', + }, + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.tsx new file mode 100644 index 0000000000000..9090138ab91ee --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_name_override/rule_name_override.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 { EuiDescriptionList } from '@elastic/eui'; +import * as ruleDetailsI18n from '../../../../translations'; +import type { RuleNameOverrideObject } from '../../../../../../../../../common/api/detection_engine'; +import { RuleNameOverride } from '../../../../rule_about_section'; + +interface RuleNameOverrideReadOnlyProps { + ruleNameOverride?: RuleNameOverrideObject; +} + +export function RuleNameOverrideReadOnly({ ruleNameOverride }: RuleNameOverrideReadOnlyProps) { + if (!ruleNameOverride) { + return null; + } + + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx new file mode 100644 index 0000000000000..9e6be8a3cbe82 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.stories.tsx @@ -0,0 +1,37 @@ +/* + * 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 { RuleScheduleReadOnly } from './rule_schedule'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: RuleScheduleReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/rule_schedule', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + rule_schedule: { + interval: '5m', + lookback: '60s', + }, + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.tsx new file mode 100644 index 0000000000000..24d0e5d6e05f1 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/rule_schedule/rule_schedule.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 { EuiDescriptionList } from '@elastic/eui'; +import { parseDuration } from '@kbn/alerting-plugin/common'; +import * as i18n from '../../../../translations'; +import type { RuleSchedule } from '../../../../../../../../../common/api/detection_engine'; +import { AccessibleTimeValue } from '../../../../rule_schedule_section'; +import { secondsToDurationString } from '../../../../../../../../detections/pages/detection_engine/rules/helpers'; + +interface RuleScheduleReadOnlyProps { + ruleSchedule: RuleSchedule; +} + +export function RuleScheduleReadOnly({ ruleSchedule }: RuleScheduleReadOnlyProps) { + const lookbackSeconds = parseDuration(ruleSchedule.lookback) / 1000; + const lookbackHumanized = secondsToDurationString(lookbackSeconds); + + return ( + , + }, + { + title: i18n.FROM_FIELD_LABEL, + description: , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.stories.tsx new file mode 100644 index 0000000000000..f610cbf9eafbb --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.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 { SetupReadOnly } from './setup'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: SetupReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/setup', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + setup: + 'The \'PowerShell Script Block Logging\' logging policy must be enabled.\nSteps to implement the logging policy with Advanced Audit Configuration:\n\n```\nComputer Configuration >\nAdministrative Templates >\nWindows PowerShell >\nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add "hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```', + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.tsx new file mode 100644 index 0000000000000..a4ed7ba9539f1 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/setup/setup.tsx @@ -0,0 +1,37 @@ +/* + * 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 { SetupGuide } from '../../../../../../../../../common/api/detection_engine'; +import { MarkdownRenderer } from '../../../../../../../../common/components/markdown_editor'; + +interface SetupReadOnlyProps { + setup: SetupGuide; +} + +export function SetupReadOnly({ setup }: SetupReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} + +interface SetupProps { + setup: SetupGuide; +} + +function Setup({ setup }: SetupProps) { + return {setup}; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.stories.tsx new file mode 100644 index 0000000000000..51956bb27fa0e --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.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 { SeverityReadOnly } from './severity'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: SeverityReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/severity', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + severity: 'high', + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.tsx new file mode 100644 index 0000000000000..71ab7bf07d793 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/severity/severity.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 { Severity } from '../../../../../../../../../common/api/detection_engine'; +import { SeverityBadge } from '../../../../../../../../common/components/severity_badge'; + +interface SeverityReadOnlyProps { + severity: Severity; +} + +export function SeverityReadOnly({ severity }: SeverityReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.stories.tsx new file mode 100644 index 0000000000000..0e3408aae043e --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.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 { ThreatLanguageReadOnly } from './threat_language'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockThreatMatchRule } from '../../storybook/mocks'; + +export default { + component: ThreatLanguageReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/threat_language', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockThreatMatchRule({ + threat_language: 'lucene', + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.tsx new file mode 100644 index 0000000000000..df43373783b1b --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threat_language/threat_language.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 { EuiDescriptionList } from '@elastic/eui'; +import * as ruleDetailsI18n from '../../../../translations'; +import type { KqlQueryLanguage } from '../../../../../../../../../common/api/detection_engine'; +import { getQueryLanguageLabel } from '../../../../helpers'; + +interface ThreatLanguageReadOnlyProps { + threatLanguage?: KqlQueryLanguage; +} + +export function ThreatLanguageReadOnly({ threatLanguage }: ThreatLanguageReadOnlyProps) { + if (!threatLanguage) { + return null; + } + + return ( + + ); +} 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 28b4cd65ba78b..bbc5b19d7e66a 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 @@ -26,12 +26,12 @@ export default { interface TemplateProps { finalDiffableRule: DiffableRule; - kibanaServicesMock?: Record; + kibanaServicesOverrides?: Record; } const Template: Story = (args) => { return ( - + ); @@ -44,7 +44,7 @@ ThreatQueryWithIndexPatterns.args = { threat_query: inlineKqlQuery, data_source: dataSourceWithIndexPatterns, }), - kibanaServicesMock: { + kibanaServicesOverrides: { data: { dataViews: { create: async () => mockDataView(), @@ -60,7 +60,7 @@ ThreatQueryWithDataView.args = { threat_query: inlineKqlQuery, data_source: dataSourceWithDataView, }), - kibanaServicesMock: { + kibanaServicesOverrides: { data: { dataViews: { get: async () => mockDataView(), diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.stories.tsx new file mode 100644 index 0000000000000..8dfee48ba7d23 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.stories.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 { Story } from '@storybook/react'; +import { ThresholdReadOnly } from './threshold'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockThresholdRule } from '../../storybook/mocks'; + +export default { + component: ThresholdReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/threshold', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockThresholdRule({ + threshold: { + field: ['Responses.process.pid'], + value: 100, + cardinality: [{ field: 'host.id', value: 2 }], + }, + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.tsx new file mode 100644 index 0000000000000..19e2b824a9ce5 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/threshold/threshold.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 { Threshold as ThresholdType } from '../../../../../../../../../common/api/detection_engine'; +import { Threshold } from '../../../../rule_definition_section'; + +interface ThresholdReadOnlyProps { + threshold: ThresholdType; +} + +export function ThresholdReadOnly({ threshold }: ThresholdReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.stories.tsx new file mode 100644 index 0000000000000..2a41b6c928963 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.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 { TiebreakerFieldReadOnly } from './tiebreaker_field'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockEqlRule } from '../../storybook/mocks'; + +export default { + component: TiebreakerFieldReadOnly, + title: + 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/tiebreaker_field', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockEqlRule({ + tiebreaker_field: 'process.name', + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.tsx new file mode 100644 index 0000000000000..10e52240748c7 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/tiebreaker_field/tiebreaker_field.tsx @@ -0,0 +1,40 @@ +/* + * 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, EuiText } from '@elastic/eui'; +import * as descriptionStepI18n from '../../../../../../../rule_creation_ui/components/description_step/translations'; +import type { TiebreakerField as TiebreakerFieldType } from '../../../../../../../../../common/api/detection_engine'; + +interface TiebreakerFieldReadOnlyProps { + tiebreakerField?: TiebreakerFieldType; +} + +export function TiebreakerFieldReadOnly({ tiebreakerField }: TiebreakerFieldReadOnlyProps) { + if (!tiebreakerField) { + return null; + } + + return ( + , + }, + ]} + /> + ); +} + +interface TiebreakerFieldProps { + tiebreakerField: TiebreakerFieldType; +} + +function TiebreakerField({ tiebreakerField }: TiebreakerFieldProps) { + return {tiebreakerField}; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.stories.tsx new file mode 100644 index 0000000000000..e8646a562dadd --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.stories.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 { Story } from '@storybook/react'; +import { TimelineTemplateReadOnly } from './timeline_template'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: TimelineTemplateReadOnly, + title: + 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/timeline_template', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + timeline_template: { + timeline_title: 'Alerts Involving a Single User Timeline', + timeline_id: 'some-timeline-id-123', + }, + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.tsx new file mode 100644 index 0000000000000..d6cc75cec5843 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timeline_template/timeline_template.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 { EuiDescriptionList } from '@elastic/eui'; +import * as ruleDetailsI18n from '../../../../translations'; +import type { TimelineTemplateReference } from '../../../../../../../../../common/api/detection_engine'; +import { TimelineTitle } from '../../../../rule_definition_section'; + +interface TimelineTemplateReadOnlyProps { + timelineTemplate?: TimelineTemplateReference; +} + +export function TimelineTemplateReadOnly({ timelineTemplate }: TimelineTemplateReadOnlyProps) { + if (!timelineTemplate) { + return null; + } + + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.stories.tsx new file mode 100644 index 0000000000000..5d6b6c0a7bc3a --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.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 { TimestampFieldReadOnly } from './timestamp_field'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockEqlRule } from '../../storybook/mocks'; + +export default { + component: TimestampFieldReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/timestamp_field', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockEqlRule({ + timestamp_field: 'event.created', + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.tsx new file mode 100644 index 0000000000000..cd27bfde3db60 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_field/timestamp_field.tsx @@ -0,0 +1,40 @@ +/* + * 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, EuiText } from '@elastic/eui'; +import * as descriptionStepI18n from '../../../../../../../rule_creation_ui/components/description_step/translations'; +import type { TimestampField as TimestampFieldType } from '../../../../../../../../../common/api/detection_engine'; + +interface TimestampFieldReadOnlyProps { + timestampField?: TimestampFieldType; +} + +export function TimestampFieldReadOnly({ timestampField }: TimestampFieldReadOnlyProps) { + if (!timestampField) { + return null; + } + + return ( + , + }, + ]} + /> + ); +} + +interface TimestampFieldProps { + timestampField: TimestampFieldType; +} + +function TimestampField({ timestampField }: TimestampFieldProps) { + return {timestampField}; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.stories.tsx new file mode 100644 index 0000000000000..eaba3bda0c2e7 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.stories.tsx @@ -0,0 +1,40 @@ +/* + * 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 { TimestampOverrideReadOnly } from './timestamp_override'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: TimestampOverrideReadOnly, + title: + 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/timestamp_override', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ( + + ); +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + timestamp_override: { + field_name: 'event.ingested', + fallback_disabled: true, + }, + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.tsx new file mode 100644 index 0000000000000..5d4c6ba3e1d2b --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/timestamp_override/timestamp_override.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 { EuiDescriptionList } from '@elastic/eui'; +import * as ruleDetailsI18n from '../../../../translations'; +import type { TimestampOverrideObject } from '../../../../../../../../../common/api/detection_engine'; +import { TimestampOverride } from '../../../../rule_about_section'; + +interface TimestampOverrideReadOnlyProps { + timestampOverride?: TimestampOverrideObject; +} + +export function TimestampOverrideReadOnly({ timestampOverride }: TimestampOverrideReadOnlyProps) { + if (!timestampOverride) { + return null; + } + + return ( + , + }, + ]} + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.stories.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.stories.tsx new file mode 100644 index 0000000000000..e3f901c958788 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.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 { TypeReadOnly } from './type'; +import { FieldReadOnly } from '../../field_readonly'; +import type { DiffableRule } from '../../../../../../../../../common/api/detection_engine'; +import { mockCustomQueryRule } from '../../storybook/mocks'; + +export default { + component: TypeReadOnly, + title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/FieldReadOnly/type', +}; + +interface TemplateProps { + finalDiffableRule: DiffableRule; +} + +const Template: Story = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +Default.args = { + finalDiffableRule: mockCustomQueryRule({ + type: 'query', + }), +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.tsx new file mode 100644 index 0000000000000..c08a77a2c1d0c --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/fields/type/type.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 { DiffableRuleTypes } from '../../../../../../../../../common/api/detection_engine'; +import { RuleType } from '../../../../rule_definition_section'; + +interface TypeReadOnlyProps { + type: DiffableRuleTypes; +} + +export function TypeReadOnly({ type }: TypeReadOnlyProps) { + return ( + , + }, + ]} + /> + ); +} 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 index 5ebc6f80b13f2..1212905c930c7 100644 --- 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 @@ -8,6 +8,10 @@ import React from 'react'; import type { DiffableMachineLearningFields } from '../../../../../../../common/api/detection_engine'; import { MachineLearningJobIdReadOnly } from './fields/machine_learning_job_id/machine_learning_job_id'; +import { TypeReadOnly } from './fields/type/type'; +import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression'; +import { assertUnreachable } from '../../../../../../../common/utility_types'; +import { AnomalyThresholdReadOnly } from './fields/anomaly_threshold/anomaly_threshold'; interface MachineLearningRuleFieldReadOnlyProps { fieldName: keyof DiffableMachineLearningFields; @@ -19,6 +23,15 @@ export function MachineLearningRuleFieldReadOnly({ finalDiffableRule, }: MachineLearningRuleFieldReadOnlyProps) { switch (fieldName) { + case 'anomaly_threshold': + return ; + case 'alert_suppression': + return ( + + ); case 'machine_learning_job_id': return ( ); case 'type': - return null; + return ; default: - return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + return assertUnreachable(fieldName); } } 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 index 0e2b52c71ba2b..45eeb17f730fb 100644 --- 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 @@ -9,6 +9,11 @@ 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'; +import { TypeReadOnly } from './fields/type/type'; +import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression'; +import { NewTermsFieldsReadOnly } from './fields/new_terms_fields/new_terms_fields'; +import { HistoryWindowStartReadOnly } from './fields/history_window_start/history_window_start'; +import { assertUnreachable } from '../../../../../../../common/utility_types'; interface NewTermsRuleFieldReadOnlyProps { fieldName: keyof DiffableNewTermsFields; @@ -20,8 +25,19 @@ export function NewTermsRuleFieldReadOnly({ finalDiffableRule, }: NewTermsRuleFieldReadOnlyProps) { switch (fieldName) { + case 'alert_suppression': + return ( + + ); case 'data_source': return ; + case 'history_window_start': + return ( + + ); case 'kql_query': return ( ); + case 'new_terms_fields': + return ; case 'type': - return null; + return ; default: - return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + return assertUnreachable(fieldName); } } 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 index 41e2e0c32108b..e4a5dbf7242d1 100644 --- 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 @@ -9,6 +9,9 @@ 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'; +import { TypeReadOnly } from './fields/type/type'; +import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression'; +import { assertUnreachable } from '../../../../../../../common/utility_types'; interface SavedQueryRuleFieldReadOnlyProps { fieldName: keyof DiffableSavedQueryFields; @@ -20,6 +23,13 @@ export function SavedQueryRuleFieldReadOnly({ finalDiffableRule, }: SavedQueryRuleFieldReadOnlyProps) { switch (fieldName) { + case 'alert_suppression': + return ( + + ); case 'data_source': return ; case 'kql_query': @@ -31,8 +41,8 @@ export function SavedQueryRuleFieldReadOnly({ /> ); case 'type': - return null; + return ; default: - return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + return assertUnreachable(fieldName); } } 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 854251450809f..4612852c0ff7e 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 @@ -16,9 +16,11 @@ import type { DiffableEqlFields, DiffableEsqlFields, DiffableMachineLearningFields, + DiffableNewTermsFields, DiffableRule, DiffableSavedQueryFields, DiffableThreatMatchFields, + DiffableThresholdFields, InlineKqlQuery, RuleEqlQuery, SavedKqlQuery, @@ -274,3 +276,49 @@ export function mockThreatMatchRule( ...overrides, }; } + +const newTermsDiffableRuleFields: DiffableNewTermsFields = { + type: 'new_terms', + kql_query: { + type: KqlQueryType.inline_query, + query: '*', + language: 'kuery', + filters: [], + }, + new_terms_fields: ['host.name'], + history_window_start: 'now-7d', +}; + +export function mockNewTermsRule( + overrides: Partial +): DiffableRule { + return { + ...commonDiffableRuleFields, + ...newTermsDiffableRuleFields, + ...overrides, + }; +} + +export const thresholdDiffableRuleFields: DiffableThresholdFields = { + type: 'threshold', + kql_query: { + type: KqlQueryType.inline_query, + query: '*', + language: 'kuery', + filters: [], + }, + threshold: { + field: ['user.name'], + value: 200, + }, +}; + +export function mockThresholdRule( + overrides: Partial +): DiffableRule { + return { + ...commonDiffableRuleFields, + ...thresholdDiffableRuleFields, + ...overrides, + }; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/three_way_diff_storybook_providers.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/three_way_diff_storybook_providers.tsx index 483624b6fb408..4eb14440c056c 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/three_way_diff_storybook_providers.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_readonly/storybook/three_way_diff_storybook_providers.tsx @@ -11,8 +11,10 @@ import { merge } from 'lodash'; import { Subject } from 'rxjs'; import { Provider as ReduxStoreProvider } from 'react-redux'; import type { CoreStart } from '@kbn/core/public'; +import type { UpsellingService } from '@kbn/security-solution-upselling/service'; import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; import { ReactQueryClientProvider } from '../../../../../../../common/containers/query_client/query_client_provider'; +import { UpsellingProvider } from '../../../../../../../common/components/upselling_provider'; function createKibanaServicesMock(overrides?: Partial) { const baseMock = { @@ -44,6 +46,10 @@ function createKibanaServicesMock(overrides?: Partial) { }, }, uiSettings: {}, + upsellingService: { + messages$: new Subject(), + getMessagesValue: () => new Map(), + } as unknown as UpsellingService, }; return merge(baseMock, overrides); @@ -65,21 +71,26 @@ function createMockStore() { interface StorybookProvidersProps { children: React.ReactNode; - kibanaServicesMock?: Record; + kibanaServicesOverrides?: Record; } export function ThreeWayDiffStorybookProviders({ children, - kibanaServicesMock, + kibanaServicesOverrides, }: StorybookProvidersProps) { - const KibanaReactContext = createKibanaReactContext(createKibanaServicesMock(kibanaServicesMock)); + const kibanaServicesMock = createKibanaServicesMock(kibanaServicesOverrides); + const KibanaReactContext = createKibanaReactContext(kibanaServicesMock); const store = createMockStore(); return ( - {children} + + + {children} + + ); 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 index 11fd941601922..3e23a064d14f2 100644 --- 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 @@ -13,6 +13,10 @@ 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'; +import { TypeReadOnly } from './fields/type/type'; +import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression'; +import { assertUnreachable } from '../../../../../../../common/utility_types'; +import { ThreatLanguageReadOnly } from './fields/threat_language/threat_language'; interface ThreatMatchRuleFieldReadOnlyProps { fieldName: keyof DiffableThreatMatchFields; @@ -24,6 +28,13 @@ export function ThreatMatchRuleFieldReadOnly({ finalDiffableRule, }: ThreatMatchRuleFieldReadOnlyProps) { switch (fieldName) { + case 'alert_suppression': + return ( + + ); case 'data_source': return ; case 'kql_query': @@ -42,6 +53,8 @@ export function ThreatMatchRuleFieldReadOnly({ threatIndicatorPath={finalDiffableRule.threat_indicator_path} /> ); + case 'threat_language': + return ; case 'threat_mapping': return ; case 'threat_query': @@ -52,8 +65,8 @@ export function ThreatMatchRuleFieldReadOnly({ /> ); case 'type': - return null; + return ; default: - return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + return assertUnreachable(fieldName); } } 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 index da7d3984d7ccb..d3208a055fa48 100644 --- 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 @@ -9,6 +9,10 @@ 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'; +import { TypeReadOnly } from './fields/type/type'; +import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression'; +import { assertUnreachable } from '../../../../../../../common/utility_types'; +import { ThresholdReadOnly } from './fields/threshold/threshold'; interface ThresholdRuleFieldReadOnlyProps { fieldName: keyof DiffableThresholdFields; @@ -20,6 +24,13 @@ export function ThresholdRuleFieldReadOnly({ finalDiffableRule, }: ThresholdRuleFieldReadOnlyProps) { switch (fieldName) { + case 'alert_suppression': + return ( + + ); case 'data_source': return ; case 'kql_query': @@ -30,9 +41,11 @@ export function ThresholdRuleFieldReadOnly({ ruleType={finalDiffableRule.type} /> ); + case 'threshold': + return ; case 'type': - return null; + return ; default: - return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented + return assertUnreachable(fieldName); } } diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx index 24f871125ce4d..8fccd1fb8ac73 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx @@ -199,6 +199,23 @@ export const getScheduleStepsData = (rule: RuleResponse): ScheduleStepRule => { }; }; +/** + * Converts seconds to duration string, like "1h", "30m" or "15s" + */ +export const secondsToDurationString = (seconds: number): string => { + if (seconds === 0) { + return `0s`; + } + + if (seconds % 3600 === 0) { + return `${seconds / 3600}h`; + } else if (seconds % 60 === 0) { + return `${seconds / 60}m`; + } else { + return `${seconds}s`; + } +}; + export const getHumanizedDuration = (from: string, interval: string): string => { const fromValue = dateMath.parse(from) ?? moment(); const intervalValue = dateMath.parse(`now-${interval}`) ?? moment(); @@ -208,17 +225,8 @@ export const getHumanizedDuration = (from: string, interval: string): string => // Basing calculations off floored seconds count as moment durations weren't precise const intervalDuration = Math.floor(fromDuration.asSeconds()); // For consistency of display value - if (intervalDuration === 0) { - return `0s`; - } - if (intervalDuration % 3600 === 0) { - return `${intervalDuration / 3600}h`; - } else if (intervalDuration % 60 === 0) { - return `${intervalDuration / 60}m`; - } else { - return `${intervalDuration}s`; - } + return secondsToDurationString(intervalDuration); }; export const getAboutStepsData = (rule: RuleResponse, detailsView: boolean): AboutStepRule => {