-
- {reference.value}
-
-
+
+
+
+
+ Source
+ {prePackaged ? 'Sigma' : 'Custom'}
+
+ {prePackaged ? (
+
+ License
+
+ Detection Rule License (DLR)
+
+
+ ) : null}
+
+
+
+
+
+
+ Rule level
+ {ruleData.level}
+
+
+
+
+
+
Tags
+ {ruleData.tags.length > 0 ? (
+
+ {ruleData.tags.map((tag: any, i: number) => (
+
+ {tag.value}
+
+ ))}
+
+ ) : (
+
{DEFAULT_EMPTY_DATA}
+ )}
+
+
+
+
+
References
+ {ruleData.references.length > 0 ? (
+ ruleData.references.map((reference: any, i: number) => (
+
+
+ {reference.value}
+
+
+
+ ))
+ ) : (
+
{DEFAULT_EMPTY_DATA}
+ )}
+
+
+
+
False positive cases
+
+ {ruleData.false_positives.length > 0 ? (
+ ruleData.false_positives.map((falsepositive: any, i: number) => (
+
+ {falsepositive.value}
+
+
+ ))
+ ) : (
+
{DEFAULT_EMPTY_DATA}
+ )}
- ))
- ) : (
-
{DEFAULT_EMPTY_DATA}
- )}
-
-
-
False positive cases
-
- {ruleData.false_positives.length > 0 ? (
- ruleData.false_positives.map((falsepositive: any, i: number) => (
-
- {falsepositive.value}
-
-
- ))
- ) : (
-
{DEFAULT_EMPTY_DATA}
- )}
-
-
-
-
-
Rule Status
-
{ruleData.status}
-
-
-
-
-
- {ruleData.detection}
-
-
+
+
+
Rule Status
+
{ruleData.status}
+
+
+
+
+
+ {ruleData.detection}
+
+
+ >
+ )}
+ {selectedEditorType === 'yaml' && (
+
+
+
+ )}
);
};
diff --git a/public/pages/Rules/components/RuleContentViewer/RuleContentYamlViewer.test.tsx b/public/pages/Rules/components/RuleContentViewer/RuleContentYamlViewer.test.tsx
new file mode 100644
index 000000000..8c1571c8d
--- /dev/null
+++ b/public/pages/Rules/components/RuleContentViewer/RuleContentYamlViewer.test.tsx
@@ -0,0 +1,51 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from 'react';
+import { render } from '@testing-library/react';
+import { RuleContentYamlViewer } from './RuleContentYamlViewer';
+
+describe('
spec', () => {
+ it('renders the component', () => {
+ const { container } = render(
+
+ );
+ expect(container.firstChild).toMatchSnapshot();
+ });
+});
diff --git a/public/pages/Rules/components/RuleContentViewer/RuleContentYamlViewer.tsx b/public/pages/Rules/components/RuleContentViewer/RuleContentYamlViewer.tsx
new file mode 100644
index 000000000..bf92ea056
--- /dev/null
+++ b/public/pages/Rules/components/RuleContentViewer/RuleContentYamlViewer.tsx
@@ -0,0 +1,24 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { EuiCodeBlock } from '@elastic/eui';
+import React from 'react';
+import { mapRuleToYamlObject, mapYamlObjectToYamlString } from '../../utils/mappers';
+import { Rule } from '../../../../../models/interfaces';
+
+export interface RuleContentYamlViewerProps {
+ rule: Rule;
+}
+
+export const RuleContentYamlViewer: React.FC
= ({ rule }) => {
+ const yamlObject = mapRuleToYamlObject(rule);
+ const ruleYaml = mapYamlObjectToYamlString(yamlObject);
+
+ return (
+
+ {ruleYaml}
+
+ );
+};
diff --git a/public/pages/Rules/components/RuleContentViewer/__snapshots__/RuleContentViewer.test.tsx.snap b/public/pages/Rules/components/RuleContentViewer/__snapshots__/RuleContentViewer.test.tsx.snap
new file mode 100644
index 000000000..891a04d01
--- /dev/null
+++ b/public/pages/Rules/components/RuleContentViewer/__snapshots__/RuleContentViewer.test.tsx.snap
@@ -0,0 +1,341 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` spec renders the component 1`] = `
+
+
+
+
+
+
+
+
+ My Rule
+
+
+
+
+
+ dns
+
+
+
+
+
+
+ My Rule
+
+
+
+
+
+ 2022-11-22T23:00:00.000Z
+
+
+
+ aleksandar
+
+
+
+
+
+
+ Custom
+
+
+
+
+
+
+ high
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+ stable
+
+
+
+
+
+`;
diff --git a/public/pages/Rules/components/RuleContentViewer/__snapshots__/RuleContentYamlViewer.test.tsx.snap b/public/pages/Rules/components/RuleContentViewer/__snapshots__/RuleContentYamlViewer.test.tsx.snap
new file mode 100644
index 000000000..4dd890090
--- /dev/null
+++ b/public/pages/Rules/components/RuleContentViewer/__snapshots__/RuleContentYamlViewer.test.tsx.snap
@@ -0,0 +1,407 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` spec renders the component 1`] = `
+
+
+
+
+
+ id
+
+
+ :
+
+ 25b9c01c
+
+ -
+
+ 350d
+
+ -
+
+ 4b95
+
+ -
+
+ bed1
+
+ -
+
+ 836d04a4f324
+
+
+
+
+
+ logsource
+
+
+ :
+
+
+
+
+
+
+
+ product
+
+
+ :
+
+ windows
+
+
+
+
+
+ title
+
+
+ :
+
+ Testing rule
+
+
+
+
+
+ description
+
+
+ :
+
+ Testing Description
+
+
+
+
+
+ tags
+
+
+ :
+
+
+
+
+
+
+
+ -
+
+ attack.persistence
+
+
+
+
+
+ -
+
+ attack.privilege_escalation
+
+
+
+
+
+ -
+
+ attack.t1543.003
+
+
+
+
+
+ falsepositives
+
+
+ :
+
+
+
+
+
+
+
+ -
+
+ Unknown
+
+
+
+
+
+ level
+
+
+ :
+
+ high
+
+
+
+
+
+ status
+
+
+ :
+
+ experimental
+
+
+
+
+
+ references
+
+
+ :
+
+
+
+
+
+
+
+ -
+
+
+
+ 'https://securelist.com/operation-tunnelsnake-and-moriya-rootkit/101831'
+
+
+
+
+
+
+
+ author
+
+
+ :
+
+ Bhabesh Raj
+
+
+
+
+
+ detection
+
+
+ :
+
+
+
+
+
+
+
+ selection
+
+
+ :
+
+
+
+
+
+
+
+ Provider_Name
+
+
+ :
+
+ Service Control Manager
+
+
+
+
+
+ EventID
+
+
+ :
+
+
+
+ 7045
+
+
+
+
+
+
+
+ ServiceName
+
+
+ :
+
+ ZzNetSvc
+
+
+
+
+
+ condition
+
+
+ :
+
+ selection
+
+
+
+
+
+
+
+
+`;
diff --git a/public/pages/Rules/components/RuleEditor/YamlRuleEditor.tsx b/public/pages/Rules/components/RuleEditor/YamlRuleEditor.tsx
index abdb234a0..842faffef 100644
--- a/public/pages/Rules/components/RuleEditor/YamlRuleEditor.tsx
+++ b/public/pages/Rules/components/RuleEditor/YamlRuleEditor.tsx
@@ -4,7 +4,7 @@
*/
import React, { useState } from 'react';
-import { dump, load } from 'js-yaml';
+import { load } from 'js-yaml';
import { EuiFormRow, EuiCodeEditor, EuiLink, EuiSpacer, EuiText, EuiForm } from '@elastic/eui';
import FormFieldHeader from '../../../../components/FormFieldHeader';
import { Rule } from '../../../../../models/interfaces';
@@ -16,6 +16,11 @@ import {
descriptionErrorString,
titleErrorString,
} from '../../../../utils/validation';
+import {
+ mapRuleToYamlObject,
+ mapYamlObjectToYamlString,
+ mapYamlObjectToRule,
+} from '../../utils/mappers';
export interface YamlRuleEditorProps {
rule: Rule;
@@ -27,74 +32,6 @@ export interface YamlEditorState {
value?: string;
}
-const mapYamlObjectToYamlString = (rule: Rule): string => {
- try {
- if (!rule.detection) {
- const { detection, ...ruleWithoutDetection } = rule;
- return dump(ruleWithoutDetection);
- } else {
- return dump(rule);
- }
- } catch (error: any) {
- console.warn('Security Analytics - Rule Eritor - Yaml dump', error);
- return '';
- }
-};
-
-const mapRuleToYamlObject = (rule: Rule): any => {
- let detection = undefined;
- if (rule.detection) {
- try {
- detection = load(rule.detection);
- } catch {}
- }
-
- const yamlObject: any = {
- id: rule.id,
- logsource: { product: rule.category },
- title: rule.title,
- description: rule.description,
- tags: rule.tags.map((tag) => tag.value),
- falsepositives: rule.false_positives.map((falsePositive) => falsePositive.value),
- level: rule.level,
- status: rule.status,
- references: rule.references.map((reference) => reference.value),
- author: rule.author,
- detection,
- };
-
- return yamlObject;
-};
-
-const mapYamlObjectToRule = (obj: any): Rule => {
- let detection = '';
- if (obj.detection) {
- try {
- detection = dump(obj.detection);
- } catch {}
- }
- const rule: Rule = {
- id: obj.id,
- category: obj.logsource ? obj.logsource.product : undefined,
- log_source: '',
- title: obj.title,
- description: obj.description,
- tags: obj.tags ? obj.tags.map((tag: string) => ({ value: tag })) : undefined,
- false_positives: obj.falsepositives
- ? obj.falsepositives.map((falsePositive: string) => ({ value: falsePositive }))
- : undefined,
- level: obj.level,
- status: obj.status,
- references: obj.references
- ? obj.references.map((reference: string) => ({ value: reference }))
- : undefined,
- author: obj.author,
- detection,
- };
-
- return rule;
-};
-
const validateRule = (rule: Rule): string[] | null => {
const requiredFiledsValidationErrors: Array = [];
diff --git a/public/pages/Rules/utils/mappers.ts b/public/pages/Rules/utils/mappers.ts
new file mode 100644
index 000000000..4956865aa
--- /dev/null
+++ b/public/pages/Rules/utils/mappers.ts
@@ -0,0 +1,70 @@
+import { dump, load } from 'js-yaml';
+import { Rule } from '../../../../models/interfaces';
+
+export const mapYamlObjectToYamlString = (rule: Rule): string => {
+ try {
+ if (!rule.detection) {
+ const { detection, ...ruleWithoutDetection } = rule;
+ return dump(ruleWithoutDetection);
+ } else {
+ return dump(rule);
+ }
+ } catch (error: any) {
+ console.warn('Security Analytics - Rule Eritor - Yaml dump', error);
+ return '';
+ }
+};
+
+export const mapRuleToYamlObject = (rule: Rule): any => {
+ let detection = undefined;
+ if (rule.detection) {
+ try {
+ detection = load(rule.detection);
+ } catch {}
+ }
+
+ const yamlObject: any = {
+ id: rule.id,
+ logsource: { product: rule.category },
+ title: rule.title,
+ description: rule.description,
+ tags: rule.tags.map((tag) => tag.value),
+ falsepositives: rule.false_positives.map((falsePositive) => falsePositive.value),
+ level: rule.level,
+ status: rule.status,
+ references: rule.references.map((reference) => reference.value),
+ author: rule.author,
+ detection,
+ };
+
+ return yamlObject;
+};
+
+export const mapYamlObjectToRule = (obj: any): Rule => {
+ let detection = '';
+ if (obj.detection) {
+ try {
+ detection = dump(obj.detection);
+ } catch {}
+ }
+ const rule: Rule = {
+ id: obj.id,
+ category: obj.logsource ? obj.logsource.product : undefined,
+ log_source: '',
+ title: obj.title,
+ description: obj.description,
+ tags: obj.tags ? obj.tags.map((tag: string) => ({ value: tag })) : undefined,
+ false_positives: obj.falsepositives
+ ? obj.falsepositives.map((falsePositive: string) => ({ value: falsePositive }))
+ : undefined,
+ level: obj.level,
+ status: obj.status,
+ references: obj.references
+ ? obj.references.map((reference: string) => ({ value: reference }))
+ : undefined,
+ author: obj.author,
+ detection,
+ };
+
+ return rule;
+};