Skip to content

Commit

Permalink
Merge branch 'main' into feature/update_vertical_domain
Browse files Browse the repository at this point in the history
  • Loading branch information
AWSHurneyt authored Feb 16, 2023
2 parents e6055f5 + 4b22e07 commit 4f27277
Show file tree
Hide file tree
Showing 9 changed files with 295 additions and 217 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"husky": "^3.0.0",
"jest-cli": "^27.5.1",
"jest-environment-jsdom": "^27.5.1",
"lint-staged": "^9.2.0",
"lint-staged": "^10.2.0",
"ts-loader": "^6.2.1"
},
"engines": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import {
} from '../utils/helpers';
import { NotificationsService } from '../../../../../services';
import { validateName } from '../../../../../utils/validation';
import { CoreServicesContext } from '../../../../../components/core_services';
import { BREADCRUMBS } from '../../../../../utils/constants';

interface ConfigureAlertsProps extends RouteComponentProps {
detector: Detector;
Expand All @@ -45,6 +47,8 @@ interface ConfigureAlertsState {
}

export default class ConfigureAlerts extends Component<ConfigureAlertsProps, ConfigureAlertsState> {
static contextType = CoreServicesContext;

constructor(props: ConfigureAlertsProps) {
super(props);
this.state = {
Expand All @@ -55,8 +59,21 @@ export default class ConfigureAlerts extends Component<ConfigureAlertsProps, Con

componentDidMount = async () => {
const {
isEdit,
detector,
detector: { triggers },
} = this.props;

isEdit &&
this.context.chrome.setBreadcrumbs([
BREADCRUMBS.SECURITY_ANALYTICS,
BREADCRUMBS.DETECTORS,
BREADCRUMBS.DETECTORS_DETAILS(detector.name, detector.id),
{
text: 'Edit alert triggers',
},
]);

this.getNotificationChannels();
if (triggers.length === 0) {
this.addCondition();
Expand Down Expand Up @@ -100,15 +117,18 @@ export default class ConfigureAlerts extends Component<ConfigureAlertsProps, Con

render() {
const {
isEdit,
detector: { triggers },
} = this.props;
const { loading, notificationChannels } = this.state;
return (
<div>
<EuiTitle size={'m'}>
<h3>
{createDetectorSteps[DetectorCreationStep.CONFIGURE_ALERTS].title +
` (${triggers.length})`}
{isEdit
? 'Edit alert triggers'
: createDetectorSteps[DetectorCreationStep.CONFIGURE_ALERTS].title +
` (${triggers.length})`}
</h3>
</EuiTitle>

Expand All @@ -126,7 +146,7 @@ export default class ConfigureAlerts extends Component<ConfigureAlertsProps, Con
id={`alert-condition-${index}`}
buttonContent={
<EuiTitle>
<h4>Alert trigger</h4>
<h4>{alertCondition.name}</h4>
</EuiTitle>
}
paddingSize={'none'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,12 @@ export default class UpdateAlertConditions extends Component<
> {
constructor(props: UpdateAlertConditionsProps) {
super(props);
const detector = {
...props.location.state.detectorHit._source,
id: props.location.state.detectorHit._id,
};
this.state = {
detector: props.location.state.detectorHit._source,
detector,
rules: {},
rulesOptions: [],
submitting: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ import { IndexService, ServicesContext } from '../../../../services';
import { DetectorSchedule } from '../../../CreateDetector/components/DefineDetector/components/DetectorSchedule/DetectorSchedule';
import { useCallback } from 'react';
import { DetectorHit, SearchDetectorsResponse } from '../../../../../server/models/interfaces';
import { EMPTY_DEFAULT_DETECTOR, ROUTES } from '../../../../utils/constants';
import { BREADCRUMBS, EMPTY_DEFAULT_DETECTOR, ROUTES } from '../../../../utils/constants';
import { ServerResponse } from '../../../../../server/models/types';
import { NotificationsStart } from 'opensearch-dashboards/public';
import { errorNotificationToast, successNotificationToast } from '../../../../utils/helpers';
import { CoreServicesContext } from '../../../../components/core_services';

export interface UpdateDetectorBasicDetailsProps
extends RouteComponentProps<any, any, { detectorHit: DetectorHit }> {
Expand All @@ -41,6 +42,8 @@ export const UpdateDetectorBasicDetails: React.FC<UpdateDetectorBasicDetailsProp
const description = inputs[0].detector_input.description;
const detectorId = props.location.pathname.replace(`${ROUTES.EDIT_DETECTOR_DETAILS}/`, '');

const context = useContext(CoreServicesContext);

useEffect(() => {
const getDetector = async () => {
const response = (await services?.detectorsService.getDetectors()) as ServerResponse<
Expand All @@ -51,6 +54,15 @@ export const UpdateDetectorBasicDetails: React.FC<UpdateDetectorBasicDetailsProp
(detectorHit) => detectorHit._id === detectorId
) as DetectorHit;
setDetector(detectorHit._source);

context?.chrome.setBreadcrumbs([
BREADCRUMBS.SECURITY_ANALYTICS,
BREADCRUMBS.DETECTORS,
BREADCRUMBS.DETECTORS_DETAILS(detectorHit._source.name, detectorHit._id),
{
text: 'Edit detector details',
},
]);
props.history.replace({
pathname: `${ROUTES.EDIT_DETECTOR_DETAILS}/${detectorId}`,
state: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@

import React, { Component } from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui';
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle, EuiText } from '@elastic/eui';
import { Detector, FieldMapping } from '../../../../../models/interfaces';
import FieldMappingService from '../../../../services/FieldMappingService';
import { DetectorHit, SearchDetectorsResponse } from '../../../../../server/models/interfaces';
import { EMPTY_DEFAULT_DETECTOR, ROUTES } from '../../../../utils/constants';
import { BREADCRUMBS, EMPTY_DEFAULT_DETECTOR, ROUTES } from '../../../../utils/constants';
import { DetectorsService } from '../../../../services';
import { ServerResponse } from '../../../../../server/models/types';
import { NotificationsStart } from 'opensearch-dashboards/public';
import { errorNotificationToast, successNotificationToast } from '../../../../utils/helpers';
import EditFieldMappings from '../../containers/FieldMappings/EditFieldMapping';
import { CoreServicesContext } from '../../../../components/core_services';

export interface UpdateFieldMappingsProps
extends RouteComponentProps<any, any, { detectorHit: DetectorHit }> {
Expand All @@ -35,6 +36,8 @@ export default class UpdateFieldMappings extends Component<
UpdateFieldMappingsProps,
UpdateFieldMappingsState
> {
static contextType = CoreServicesContext;

constructor(props: UpdateFieldMappingsProps) {
super(props);
const { location } = props;
Expand Down Expand Up @@ -66,6 +69,15 @@ export default class UpdateFieldMappings extends Component<
const detector = detectorHit._source;
detector.detector_type = detector.detector_type.toLowerCase();

this.context.chrome.setBreadcrumbs([
BREADCRUMBS.SECURITY_ANALYTICS,
BREADCRUMBS.DETECTORS,
BREADCRUMBS.DETECTORS_DETAILS(detectorHit._source.name, detectorHit._id),
{
text: 'Edit field mapping',
},
]);

history.replace({
pathname: `${ROUTES.EDIT_FIELD_MAPPINGS}/${detectorId}`,
state: {
Expand Down Expand Up @@ -156,6 +168,14 @@ export default class UpdateFieldMappings extends Component<
<EuiTitle size={'m'}>
<h3>Edit detector details</h3>
</EuiTitle>

<EuiText size="s" color="subdued">
To perform threat detections, your data source will need to be in a common schema format.
<br />
Rule field names are automatically mapped to the most common fields in your log data
source.
</EuiText>

<EuiSpacer size={'xxl'} />

{!loading && (
Expand Down
74 changes: 47 additions & 27 deletions public/pages/Detectors/components/UpdateRules/UpdateRules.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ import { RouteComponentProps } from 'react-router-dom';
import { RuleItem } from '../../../CreateDetector/components/DefineDetector/components/DetectionRules/types/interfaces';
import { Detector } from '../../../../../models/interfaces';
import { DetectionRulesTable } from '../../../CreateDetector/components/DefineDetector/components/DetectionRules/DetectionRulesTable';
import { EMPTY_DEFAULT_DETECTOR, ROUTES } from '../../../../utils/constants';
import { BREADCRUMBS, EMPTY_DEFAULT_DETECTOR, ROUTES } from '../../../../utils/constants';
import { ServicesContext } from '../../../../services';
import { ServerResponse } from '../../../../../server/models/types';
import { NotificationsStart } from 'opensearch-dashboards/public';
import { CoreServicesContext } from '../../../../components/core_services';
import { errorNotificationToast, successNotificationToast } from '../../../../utils/helpers';
import { RuleTableItem } from '../../../Rules/utils/helpers';
import { RuleViewerFlyout } from '../../../Rules/components/RuleViewerFlyout/RuleViewerFlyout';
import { RulesViewModelActor } from '../../../Rules/models/RulesViewModelActor';
import { ContentPanel } from '../../../../components/ContentPanel';

export interface UpdateDetectorRulesProps
extends RouteComponentProps<
Expand All @@ -47,6 +49,8 @@ export const UpdateDetectorRules: React.FC<UpdateDetectorRulesProps> = (props) =
[services]
);

const context = useContext(CoreServicesContext);

useEffect(() => {
const getDetector = async () => {
setLoading(true);
Expand All @@ -59,6 +63,15 @@ export const UpdateDetectorRules: React.FC<UpdateDetectorRulesProps> = (props) =
) as DetectorHit;
const newDetector = { ...detectorHit._source, id: detectorId };
setDetector(newDetector);

context?.chrome.setBreadcrumbs([
BREADCRUMBS.SECURITY_ANALYTICS,
BREADCRUMBS.DETECTORS,
BREADCRUMBS.DETECTORS_DETAILS(detectorHit._source.name, detectorHit._id),
{
text: 'Edit detector rules',
},
]);
await getRules(newDetector);
} else {
errorNotificationToast(props.notifications, 'retrieve', 'detector', response.error);
Expand Down Expand Up @@ -209,34 +222,41 @@ export const UpdateDetectorRules: React.FC<UpdateDetectorRulesProps> = (props) =
</EuiTitle>
<EuiSpacer size="xl" />

<DetectionRulesTable
loading={loading}
ruleItems={ruleItems}
onRuleActivationToggle={onToggle}
onAllRulesToggled={onAllRulesToggle}
onRuleDetails={onRuleDetails}
/>
<ContentPanel
title={`Detection rules (${
prePackagedRuleItems.concat(customRuleItems).filter((item) => item.active).length
})`}
>
<DetectionRulesTable
loading={loading}
ruleItems={ruleItems}
onRuleActivationToggle={onToggle}
onAllRulesToggled={onAllRulesToggle}
onRuleDetails={onRuleDetails}
/>

<EuiSpacer size="xl" />
<EuiSpacer size="xl" />

<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem grow={false}>
<EuiButton disabled={submitting} onClick={onCancel}>
Cancel
</EuiButton>
</EuiFlexItem>

<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem grow={false}>
<EuiButton disabled={submitting} onClick={onCancel}>
Cancel
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
disabled={loading}
fill={true}
isLoading={submitting}
onClick={onSave}
data-test-subj={'save-detector-rules-edits'}
>
Save changes
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiButton
disabled={loading}
fill={true}
isLoading={submitting}
onClick={onSave}
data-test-subj={'save-detector-rules-edits'}
>
Save changes
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</ContentPanel>
</div>
);
};
4 changes: 4 additions & 0 deletions public/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ export const BREADCRUMBS = Object.freeze({
text: `${name}`,
href: `#${ROUTES.DETECTOR_DETAILS}/${detectorId}`,
}),
DETECTORS_EDIT_DETAILS: (name: string, detectorId: string) => ({
text: `${name}`,
href: `#${ROUTES.EDIT_DETECTOR_DETAILS}/${detectorId}`,
}),
RULES: { text: 'Rules', href: `#${ROUTES.RULES}` },
ALERTS: { text: 'Alerts', href: `#${ROUTES.ALERTS}` },
RULES_CREATE: { text: 'Create rule', href: `#${ROUTES.RULES_CREATE}` },
Expand Down
2 changes: 1 addition & 1 deletion public/utils/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function createTextDetailsGroup(
columnNum?: number
) {
const createFormRow = (label: string, content: string, url?: string) => {
const dataTestSubj = label.toLowerCase().replaceAll(' ', '-');
const dataTestSubj = label.toLowerCase().replace(/ /g, '-');
return (
<EuiFormRow label={<EuiText color={'subdued'}>{label}</EuiText>}>
{url ? (
Expand Down
Loading

0 comments on commit 4f27277

Please sign in to comment.