Skip to content

Commit

Permalink
Added categories for log types (#741) (#742)
Browse files Browse the repository at this point in the history
* added categories for log types

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

* fixed cypress tests

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

---------

Signed-off-by: Amardeepsingh Siglani <[email protected]>
(cherry picked from commit 3ce112b)

Co-authored-by: Amardeepsingh Siglani <[email protected]>
  • Loading branch information
opensearch-trigger-bot[bot] and amsiglan authored Oct 5, 2023
1 parent 9c53b77 commit 5d3afed
Show file tree
Hide file tree
Showing 20 changed files with 261 additions and 90 deletions.
12 changes: 7 additions & 5 deletions cypress/integration/2_rules.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const SAMPLE_RULE = {
logType: 'windows',
description: 'This is a rule used to test the rule creation workflow.',
detectionLine: ['condition: Selection_1', 'Selection_1:', 'FieldKey|contains:', '- FieldValue'],
severity: 'critical',
severity: 'Critical',
tags: ['attack.persistence', 'attack.privilege_escalation', 'attack.t1543.003'],
references: 'https://nohello.com',
falsePositive: 'unknown',
Expand All @@ -31,7 +31,7 @@ const YAML_RULE_LINES = [
`- ${SAMPLE_RULE.tags[2]}`,
`falsepositives:`,
`- ${SAMPLE_RULE.falsePositive}`,
`level: ${SAMPLE_RULE.severity}`,
`level: ${SAMPLE_RULE.severity.toLowerCase()}`,
`status: ${SAMPLE_RULE.status}`,
`references:`,
`- '${SAMPLE_RULE.references}'`,
Expand Down Expand Up @@ -67,7 +67,9 @@ const checkRulesFlyout = () => {
cy.get('[data-test-subj="rule_flyout_rule_source"]').contains('Custom');

// Validate severity
cy.get('[data-test-subj="rule_flyout_rule_severity"]').contains(SAMPLE_RULE.severity);
cy.get('[data-test-subj="rule_flyout_rule_severity"]').contains(
SAMPLE_RULE.severity.toLowerCase()
);

// Validate tags
SAMPLE_RULE.tags.forEach((tag) =>
Expand Down Expand Up @@ -159,7 +161,7 @@ const fillCreateForm = () => {
getAuthorField().type(`${SAMPLE_RULE.author}`);

// rule details
getLogTypeField().type(SAMPLE_RULE.logType);
getLogTypeField().selectComboboxItem(SAMPLE_RULE.logType);
getRuleLevelField().selectComboboxItem(SAMPLE_RULE.severity);

// rule detection
Expand Down Expand Up @@ -548,7 +550,7 @@ describe('Rules', () => {
SAMPLE_RULE.logType = 'dns';
YAML_RULE_LINES[2] = `product: ${SAMPLE_RULE.logType}`;
YAML_RULE_LINES[3] = `title: ${SAMPLE_RULE.name}`;
getLogTypeField().type(SAMPLE_RULE.logType).type('{enter}');
getLogTypeField().selectComboboxItem(SAMPLE_RULE.logType);
getLogTypeField().containsValue(SAMPLE_RULE.logType).contains(SAMPLE_RULE.logType);

SAMPLE_RULE.description += ' edited';
Expand Down
2 changes: 1 addition & 1 deletion cypress/integration/3_alerts.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ describe('Alerts', () => {
expect($tr, `timestamp`).to.contain(date);
expect($tr, `rule name`).to.contain('Cypress USB Rule');
expect($tr, `detector name`).to.contain(testDetector.name);
expect($tr, `log type`).to.contain('windows');
expect($tr, `log type`).to.contain('System Activity: Windows');
});

// Close the flyout
Expand Down
2 changes: 1 addition & 1 deletion cypress/integration/4_findings.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe('Findings', () => {
cy.contains('No items found').should('not.exist');

// Check for expected findings
cy.contains('windows');
cy.contains('System Activity: Windows');
cy.contains('High');
});

Expand Down
5 changes: 4 additions & 1 deletion cypress/support/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ Cypress.Commands.add(
items = [items];
}
Cypress.log({ message: `Select combobox items: ${items.join(' | ')}` });
items.map((item) => cy.wrap(subject).type(item).type('{enter}'));
items.map((item) => {
cy.wrap(subject).type(item);
cy.get(`[title="${item}"]`).click({ force: true });
});
}
);

Expand Down
21 changes: 21 additions & 0 deletions public/components/Utility/LogCategoryOption.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { EuiTitle } from '@elastic/eui';
import React, { useEffect, useRef } from 'react';

export const LogCategoryOptionView: React.FC<{ categoryName: string }> = ({ categoryName }) => {
const inputRef = useRef<HTMLHeadingElement | null>(null);

useEffect(() => {
inputRef.current?.closest('button.euiFilterSelectItem')?.setAttribute('disabled', 'true');
}, [inputRef.current]);

return (
<EuiTitle size="xxs">
<h4 ref={inputRef}>{categoryName}</h4>
</EuiTitle>
);
};
14 changes: 9 additions & 5 deletions public/pages/Correlations/containers/CreateCorrelationRule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import { CoreServicesContext } from '../../../components/core_services';
import { RouteComponentProps, useParams } from 'react-router-dom';
import { validateName } from '../../../utils/validation';
import { FieldMappingService, IndexService } from '../../../services';
import { errorNotificationToast } from '../../../utils/helpers';
import { errorNotificationToast, getLogTypeOptions } from '../../../utils/helpers';

export interface CreateCorrelationRuleProps {
indexService: IndexService;
Expand Down Expand Up @@ -103,6 +103,7 @@ export const CreateCorrelationRule: React.FC<CreateCorrelationRuleProps> = (
...correlationRuleStateDefaultValue,
});
const [action, setAction] = useState<CorrelationRuleAction>('Create');
const [logTypeOptions, setLogTypeOptions] = useState<any[]>([]);

useEffect(() => {
if (props.history.location.state?.rule) {
Expand All @@ -119,6 +120,12 @@ export const CreateCorrelationRule: React.FC<CreateCorrelationRuleProps> = (
setAction('Edit');
setInitialRuleValues();
}

const setupLogTypeOptions = async () => {
const options = await getLogTypeOptions();
setLogTypeOptions(options);
};
setupLogTypeOptions();
}, []);

const submit = async (values: any) => {
Expand Down Expand Up @@ -274,10 +281,7 @@ export const CreateCorrelationRule: React.FC<CreateCorrelationRuleProps> = (
isInvalid={isInvalidInputForQuery('logType')}
placeholder="Select a log type"
data-test-subj={'rule_type_dropdown'}
options={ruleTypes.map(({ label }) => ({
value: label.toLowerCase(),
label,
}))}
options={logTypeOptions}
singleSelection={{ asPlainText: true }}
onChange={(e) => {
props.handleChange(`queries[${queryIdx}].logType`)(
Expand Down
8 changes: 2 additions & 6 deletions public/pages/Correlations/utils/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ import {
CorrelationRuleQuery,
} from '../../../../types';
import { Search } from '@opensearch-project/oui/src/eui_components/basic_table';
import { ruleTypes } from '../../Rules/utils/constants';
import { FieldClause } from '@opensearch-project/oui/src/eui_components/search_bar/query/ast';
import { formatRuleType } from '../../../utils/helpers';
import { formatRuleType, getLogTypeFilterOptions } from '../../../utils/helpers';

export const getCorrelationRulesTableColumns = (
onRuleNameClick: (rule: CorrelationRule) => void,
Expand Down Expand Up @@ -110,10 +109,7 @@ export const getCorrelationRulesTableSearchConfig = (
field: 'logTypes',
name: 'Log Types',
multiSelect: 'or',
options: ruleTypes.map(({ value, label }) => ({
value,
name: label,
})),
options: getLogTypeFilterOptions(),
},
],
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { RuleItem } from '../DetectionRules/types/interfaces';
import { ruleTypes } from '../../../../../Rules/utils/constants';
import ConfigureFieldMapping from '../../../ConfigureFieldMapping';
import { ConfigureFieldMappingProps } from '../../../ConfigureFieldMapping/containers/ConfigureFieldMapping';
import { getLogTypeOptions } from '../../../../../../utils/helpers';

interface DetectorTypeProps {
detectorType: string;
Expand All @@ -30,18 +31,23 @@ interface DetectorTypeState {
}

export default class DetectorType extends Component<DetectorTypeProps, DetectorTypeState> {
private detectorTypeOptions: { value: string; label: string }[];
private detectorTypeOptions: { value: string; label: string }[] = [];
constructor(props: DetectorTypeProps) {
super(props);

this.detectorTypeOptions = ruleTypes.map(({ label }) => ({ value: label, label }));
const detectorTypeIds = this.detectorTypeOptions.map((option) => option.value);
this.state = {
fieldTouched: false,
detectorTypeIds,
detectorTypeIds: [],
};
}

async componentDidMount(): Promise<void> {
this.detectorTypeOptions = await getLogTypeOptions();
this.setState({
detectorTypeIds: ruleTypes.map((option) => option.value),
});
}

onChange = (detectorType: string) => {
this.setState({ fieldTouched: true });
this.props.onDetectorTypeChange(detectorType);
Expand All @@ -66,7 +72,13 @@ export default class DetectorType extends Component<DetectorTypeProps, DetectorT
const { detectorType } = this.props;

return (
<ContentPanel title={'Detection'} titleSize={'m'}>
<ContentPanel
title={'Detection'}
subTitleText={
'The available detection rules are automatically populated based on your selected log type. Use the toggles to select detection rules for this detector'
}
titleSize={'m'}
>
<EuiFormRow
label={
<div>
Expand Down
8 changes: 3 additions & 5 deletions public/pages/Detectors/containers/Detectors/Detectors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
capitalizeFirstLetter,
errorNotificationToast,
formatRuleType,
getLogTypeFilterOptions,
renderTime,
} from '../../../../utils/helpers';
import { CoreServicesContext } from '../../../../components/core_services';
Expand Down Expand Up @@ -298,11 +299,11 @@ export default class Detectors extends Component<DetectorsProps, DetectorsState>
detectorHits.map((detector) => (detector._source.enabled ? 'Active' : 'Inactive'))
),
];
const logType = [...new Set(detectorHits.map((detector) => detector._source.detector_type))];
const search = {
box: {
placeholder: 'Search threat detectors',
schema: true,
incremental: true,
},
filters: [
{
Expand All @@ -319,10 +320,7 @@ export default class Detectors extends Component<DetectorsProps, DetectorsState>
type: 'field_value_selection',
field: 'logType',
name: 'Log type',
options: logType.map((logType) => ({
value: logType,
name: formatRuleType(logType),
})),
options: getLogTypeFilterOptions(),
multiSelect: 'or',
} as FieldValueSelectionFilterConfigType,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,7 @@ exports[`<Detectors /> spec renders the component 1`] = `
search={
Object {
"box": Object {
"incremental": true,
"placeholder": "Search threat detectors",
"schema": true,
},
Expand All @@ -598,12 +599,7 @@ exports[`<Detectors /> spec renders the component 1`] = `
"field": "logType",
"multiSelect": "or",
"name": "Log type",
"options": Array [
Object {
"name": "-",
"value": "detector_type",
},
],
"options": Array [],
"type": "field_value_selection",
},
],
Expand All @@ -628,6 +624,7 @@ exports[`<Detectors /> spec renders the component 1`] = `
<EuiSearchBar
box={
Object {
"incremental": true,
"placeholder": "Search threat detectors",
"schema": Object {
"fields": Object {
Expand Down Expand Up @@ -669,12 +666,7 @@ exports[`<Detectors /> spec renders the component 1`] = `
"field": "logType",
"multiSelect": "or",
"name": "Log type",
"options": Array [
Object {
"name": "-",
"value": "detector_type",
},
],
"options": Array [],
"type": "field_value_selection",
},
]
Expand All @@ -697,18 +689,18 @@ exports[`<Detectors /> spec renders the component 1`] = `
className="euiFlexItem euiSearchBar__searchHolder"
>
<EuiSearchBox
incremental={false}
incremental={true}
isInvalid={false}
onSearch={[Function]}
placeholder="Search threat detectors"
query=""
>
<EuiFieldSearch
aria-label="This is a search bar. After typing your query, hit enter to filter the results lower in the page."
aria-label="This is a search bar. As you type, the results lower in the page will automatically filter."
compressed={false}
defaultValue=""
fullWidth={true}
incremental={false}
incremental={true}
inputRef={[Function]}
isClearable={true}
isInvalid={false}
Expand All @@ -732,7 +724,7 @@ exports[`<Detectors /> spec renders the component 1`] = `
isInvalid={false}
>
<input
aria-label="This is a search bar. After typing your query, hit enter to filter the results lower in the page."
aria-label="This is a search bar. As you type, the results lower in the page will automatically filter."
className="euiFieldSearch euiFieldSearch--fullWidth"
defaultValue=""
onKeyUp={[Function]}
Expand Down Expand Up @@ -800,12 +792,7 @@ exports[`<Detectors /> spec renders the component 1`] = `
"field": "logType",
"multiSelect": "or",
"name": "Log type",
"options": Array [
Object {
"name": "-",
"value": "detector_type",
},
],
"options": Array [],
"type": "field_value_selection",
},
]
Expand Down Expand Up @@ -975,12 +962,7 @@ exports[`<Detectors /> spec renders the component 1`] = `
"field": "logType",
"multiSelect": "or",
"name": "Log type",
"options": Array [
Object {
"name": "-",
"value": "detector_type",
},
],
"options": Array [],
"type": "field_value_selection",
}
}
Expand Down
Loading

0 comments on commit 5d3afed

Please sign in to comment.