Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added categories for log types #741

Merged
merged 2 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading