Skip to content

Commit

Permalink
Rules refactor (#55)
Browse files Browse the repository at this point in the history
* rewrote rules pages

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* removed unwanted changed

Signed-off-by: Amardeepsingh Siglani <[email protected]>

Signed-off-by: Amardeepsingh Siglani <[email protected]>
  • Loading branch information
amsiglan authored Nov 4, 2022
1 parent 35fd483 commit 8d3eac1
Show file tree
Hide file tree
Showing 48 changed files with 1,371 additions and 2,271 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { RuleInfo } from '../../../../../../../../server/models/interfaces';
import { RuleItemInfoBase } from '../../../../../../Rules/models/types';

export interface RuleItem {
name: string;
Expand All @@ -15,7 +15,7 @@ export interface RuleItem {
active: boolean;
}

export type RuleItemInfo = RuleInfo & { enabled: boolean; prePackaged: boolean };
export type RuleItemInfo = RuleItemInfoBase & { enabled: boolean };

export type RulesInfoByType = {
[ruleType: string]: RuleItemInfo[];
Expand Down
37 changes: 33 additions & 4 deletions public/pages/Main/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ import { ROUTES } from '../../utils/constants';
import { CoreServicesConsumer } from '../../components/core_services';
import Findings from '../Findings';
import Detectors from '../Detectors';
import Rules from '../Rules';
import Overview from '../Overview';
import CreateDetector from '../CreateDetector/containers/CreateDetector';
import Alerts from '../Alerts';
import { DetectorDetails } from '../Detectors/containers/Detector/Detector';
import { UpdateDetectorBasicDetails } from '../Detectors/components/UpdateBasicDetails/UpdateBasicDetails';
import { UpdateDetectorRules } from '../Detectors/components/UpdateRules/UpdateRules';
import Create from '../Rules/containers/Rules/components/Create';
import UpdateFieldMappings from '../Detectors/components/UpdateFieldMappings/UpdateFieldMappings';
import UpdateAlertConditions from '../Detectors/components/UpdateAlertConditions/UpdateAlertConditions';
import { Rules } from '../Rules/containers/Rules/Rules';
import { CreateRule } from '../Rules/containers/CreateRule/CreateRule';
import { EditRule } from '../Rules/containers/EditRule/EditRule';
import { ImportRule } from '../Rules/containers/ImportRule/ImportRule';
import { DuplicateRule } from '../Rules/containers/DuplicateRule/DuplicateRule';

enum Navigation {
SecurityAnalytics = 'Security Analytics',
Expand All @@ -36,7 +39,13 @@ enum Navigation {
/**
* Add here the ROUTES for pages on which the EuiPageSideBar should NOT be displayed.
*/
const HIDDEN_NAV_ROUTES: string[] = [ROUTES.DETECTORS_CREATE];
const HIDDEN_NAV_ROUTES: string[] = [
ROUTES.DETECTORS_CREATE,
ROUTES.RULES_CREATE,
ROUTES.RULES_EDIT,
ROUTES.RULES_DUPLICATE,
ROUTES.RULES_IMPORT,
];

interface MainProps extends RouteComponentProps {
landingPage: string;
Expand Down Expand Up @@ -143,7 +152,27 @@ export default class Main extends Component<MainProps, MainState> {
/>
<Route
path={ROUTES.RULES_CREATE}
render={(props: RouteComponentProps) => <Create {...props} />}
render={(props: RouteComponentProps) => (
<CreateRule services={services} history={props.history} />
)}
/>
<Route
path={ROUTES.RULES_EDIT}
render={(props: RouteComponentProps<any, any, any>) => (
<EditRule services={services} {...props} />
)}
/>
<Route
path={ROUTES.RULES_DUPLICATE}
render={(props: RouteComponentProps<any, any, any>) => (
<DuplicateRule services={services} {...props} />
)}
/>
<Route
path={ROUTES.RULES_IMPORT}
render={(props: RouteComponentProps) => (
<ImportRule services={services} history={props.history} />
)}
/>
<Route
path={ROUTES.OVERVIEW}
Expand Down
4 changes: 2 additions & 2 deletions public/pages/Overview/models/OverviewViewModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { BrowserServices } from '../../../models/interfaces';
import { DetectorHit, RuleSource } from '../../../../server/models/interfaces';
import { AlertItem, FindingItem } from './interfaces';
import { RulesService } from '../../../services';
import { RuleService } from '../../../services';
import { DEFAULT_EMPTY_DATA } from '../../../utils/constants';

export interface OverviewViewModel {
Expand Down Expand Up @@ -37,7 +37,7 @@ export class OverviewViewModelActor {

private async getRules(ruleIds: string[]): Promise<{ [id: string]: RuleSource }> {
try {
const rulesService = this.services?.ruleService as RulesService;
const rulesService = this.services?.ruleService as RuleService;
const body = {
from: 0,
size: 5000,
Expand Down
29 changes: 29 additions & 0 deletions public/pages/Rules/components/DeleteModal/DeleteModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { EuiConfirmModal } from '@elastic/eui';
import React from 'react';

export interface DeleteRuleModalProps {
title: string;
onCancel: () => void;
onConfirm: () => void;
}

export const DeleteRuleModal: React.FC<DeleteRuleModalProps> = ({ title, onCancel, onConfirm }) => {
return (
<EuiConfirmModal
title={`Delete ${title}?`}
onCancel={onCancel}
onConfirm={onConfirm}
cancelButtonText="Cancel"
confirmButtonText="Delete"
buttonColor="danger"
defaultFocusedButton="confirm"
>
<p>Delete the rule permanently? This action cannot be undone.</p>
</EuiConfirmModal>
);
};
148 changes: 148 additions & 0 deletions public/pages/Rules/components/RuleContentViewer/RuleContentViewer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import {
EuiBadge,
EuiCodeBlock,
EuiFlexGroup,
EuiFlexItem,
EuiFormLabel,
EuiFormRow,
EuiLink,
EuiModalBody,
EuiSpacer,
EuiText,
} from '@elastic/eui';
import { DEFAULT_EMPTY_DATA } from '../../../../utils/constants';
import React from 'react';
import { RuleItemInfoBase } from '../../models/types';

export interface RuleContentViewerProps {
rule: RuleItemInfoBase;
}

export const RuleContentViewer: React.FC<RuleContentViewerProps> = ({
rule: { prePackaged, _source: ruleData },
}) => {
return (
<EuiModalBody>
<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem>
<EuiFormLabel>Rule Name</EuiFormLabel>
<EuiText>{ruleData.title}</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormLabel>Log Type</EuiFormLabel>
<EuiText>{ruleData.category}</EuiText>
</EuiFlexItem>
</EuiFlexGroup>

<EuiSpacer />

<EuiFormLabel>Description</EuiFormLabel>
<EuiText>{ruleData.description || DEFAULT_EMPTY_DATA}</EuiText>
<EuiSpacer />

<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem>
<EuiFormLabel>Last Updated</EuiFormLabel>
{ruleData.last_update_time}
</EuiFlexItem>
<EuiFlexItem>
<EuiFormLabel>Author</EuiFormLabel>
{ruleData.author}
</EuiFlexItem>
</EuiFlexGroup>

<EuiSpacer />

<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem>
<EuiFormLabel>Source</EuiFormLabel>
{prePackaged ? 'Sigma' : 'Custom'}
</EuiFlexItem>
{prePackaged ? (
<EuiFlexItem>
<EuiFormLabel>License</EuiFormLabel>
<EuiLink
target={'_blank'}
href={'https://github.com/SigmaHQ/sigma/blob/master/LICENSE.Detection.Rules.md'}
>
Detection Rule License (DLR)
</EuiLink>
</EuiFlexItem>
) : null}
</EuiFlexGroup>

<EuiSpacer />

<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem>
<EuiFormLabel>Rule level</EuiFormLabel>
{ruleData.level}
</EuiFlexItem>
</EuiFlexGroup>

<EuiSpacer />

<EuiFormLabel>Tags</EuiFormLabel>
{ruleData.tags.length > 0 ? (
<EuiFlexGroup direction="row">
{ruleData.tags.map((tag: any, i: number) => (
<EuiFlexItem grow={false} key={i}>
<EuiBadge color={'#DDD'}>{tag.value}</EuiBadge>
</EuiFlexItem>
))}
</EuiFlexGroup>
) : (
<div>{DEFAULT_EMPTY_DATA}</div>
)}

<EuiSpacer />
<EuiSpacer />

<EuiFormLabel>References</EuiFormLabel>
{ruleData.references.length > 0 ? (
ruleData.references.map((reference: any, i: number) => (
<div key={i}>
<EuiLink href={reference.value} target="_blank" key={reference}>
{reference.value}
</EuiLink>
<EuiSpacer />
</div>
))
) : (
<div>{DEFAULT_EMPTY_DATA}</div>
)}

<EuiSpacer />

<EuiFormLabel>False positive cases</EuiFormLabel>
<div>
{ruleData.false_positives.length > 0 ? (
ruleData.false_positives.map((falsepositive: any, i: number) => (
<div key={i}>
{falsepositive.value}
<EuiSpacer />
</div>
))
) : (
<div>{DEFAULT_EMPTY_DATA}</div>
)}
</div>

<EuiSpacer />

<EuiFormLabel>Rule Status</EuiFormLabel>
<div>{ruleData.status}</div>

<EuiSpacer />

<EuiFormRow label="Detection" fullWidth>
<EuiCodeBlock language="yaml">{ruleData.detection}</EuiCodeBlock>
</EuiFormRow>
</EuiModalBody>
);
};
71 changes: 71 additions & 0 deletions public/pages/Rules/components/RuleEditor/FieldTextArray.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import {
EuiButton,
EuiFieldText,
EuiFlexGroup,
EuiFlexItem,
EuiFormRow,
EuiSpacer,
} from '@elastic/eui';
import React, { ChangeEvent } from 'react';

export interface FieldTextArrayProps {
label: string;
fields: string[];
addButtonName: string;
onFieldEdit: (value: string, fieldIndex: number) => void;
onFieldRemove: (fieldIndex: number) => void;
onFieldAdd: () => void;
}

export const FieldTextArray: React.FC<FieldTextArrayProps> = ({
addButtonName,
label,
fields,
onFieldEdit,
onFieldRemove,
onFieldAdd,
}) => {
return (
<>
<EuiFormRow label={label}>
<>
{fields.map((ref: string, index: number) => {
return (
<EuiFlexGroup key={index}>
<EuiFlexItem style={{ minWidth: '100%' }}>
<EuiFieldText
value={ref}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
onFieldEdit(e.target.value, index);
}}
/>
</EuiFlexItem>
{index > 0 ? (
<EuiFlexItem grow={false}>
<EuiButton onClick={() => onFieldRemove(index)}>Remove</EuiButton>
</EuiFlexItem>
) : null}
</EuiFlexGroup>
);
})}
<EuiSpacer size="s" />
<EuiButton
type="button"
className="secondary"
onClick={() => {
onFieldAdd();
}}
>
{addButtonName}
</EuiButton>
</>
</EuiFormRow>
<EuiSpacer />
</>
);
};
Loading

0 comments on commit 8d3eac1

Please sign in to comment.