Skip to content

Commit

Permalink
[Security Solution][Data Views] - Add alerts on alerts data view warn…
Browse files Browse the repository at this point in the history
…ing (elastic#138186)

## Summary

The default security data view includes the alerts index. This means that a rule that uses this data view can result in alerts on alerts. At first glance, it seems the default data view is equivalent to the default index patterns we normally display on rule creation, but it is not in that it includes the alerts index.
  • Loading branch information
yctercero authored Aug 9, 2022
1 parent f5133d4 commit b406632
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,79 @@
*/

import React from 'react';
import { shallow } from 'enzyme';
import { shallow, mount } from 'enzyme';

import { DataViewSelector } from '.';
import { useFormFieldMock } from '../../../../common/mock';
import type { DataViewSelectorProps } from '.';
import { TestProviders, useFormFieldMock } from '../../../../common/mock';

jest.mock('../../../../common/lib/kibana');

describe('data_view_selector', () => {
let mockField: DataViewSelectorProps['field'];

beforeEach(() => {
mockField = useFormFieldMock<string | undefined>({
value: undefined,
});
});

it('renders correctly', () => {
const Component = () => {
const field = useFormFieldMock({ value: '' });
// @ts-expect-error TODO: FIX THIS
return <DataViewSelector kibanaDataViews={{}} setIndexPattern={jest.fn()} field={field} />;
return <DataViewSelector kibanaDataViews={{}} field={mockField} />;
};
const wrapper = shallow(<Component />);

expect(wrapper.dive().find('[data-test-subj="pick-rule-data-source"]')).toHaveLength(1);
});

it('displays alerts on alerts warning when default security view selected', () => {
const wrapper = mount(
<TestProviders>
<DataViewSelector
kibanaDataViews={{
'security-solution-default': {
id: 'security-solution-default',
title:
'-*elastic-cloud-logs-*,.alerts-security.alerts-default,apm-*-transaction*,auditbeat-*,endgame-*,filebeat-*,logs-*,packetbeat-*,traces-apm*,winlogbeat-*',
},
'1234': {
id: '1234',
title: 'logs-*',
},
}}
field={useFormFieldMock<string | undefined>({
value: 'security-solution-default',
})}
/>
</TestProviders>
);

expect(wrapper.find('[data-test-subj="defaultSecurityDataViewWarning"]').exists()).toBeTruthy();
});

it('does not display alerts on alerts warning when default security view is not selected', () => {
const wrapper = mount(
<TestProviders>
<DataViewSelector
kibanaDataViews={{
'security-solution-default': {
id: 'security-solution-default',
title:
'-*elastic-cloud-logs-*,.alerts-security.alerts-default,apm-*-transaction*,auditbeat-*,endgame-*,filebeat-*,logs-*,packetbeat-*,traces-apm*,winlogbeat-*',
},
'1234': {
id: '1234',
title: 'logs-*',
},
}}
field={useFormFieldMock<string | undefined>({
value: '1234',
})}
/>
</TestProviders>
);

expect(wrapper.find('[data-test-subj="defaultSecurityDataViewWarning"]').exists()).toBeFalsy();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { getFieldValidityAndErrorMessage } from '../../../../shared_imports';
import * as i18n from './translations';
import type { DefineStepRule } from '../../../pages/detection_engine/rules/types';

interface DataViewSelectorProps {
export interface DataViewSelectorProps {
kibanaDataViews: Record<string, DataViewListItem>;
field: FieldHook<DefineStepRule['dataViewId']>;
}
Expand All @@ -25,6 +25,7 @@ export const DataViewSelector = ({ kibanaDataViews, field }: DataViewSelectorPro
let isInvalid;
let errorMessage;
let dataViewId: string | null | undefined;

if (field != null) {
const fieldAndError = getFieldValidityAndErrorMessage(field);
isInvalid = fieldAndError.isInvalid;
Expand Down Expand Up @@ -53,15 +54,26 @@ export const DataViewSelector = ({ kibanaDataViews, field }: DataViewSelectorPro
: []
);

const [showDataViewAlertsOnAlertsWarning, setShowDataViewAlertsOnAlertsWarning] = useState(false);

useEffect(() => {
if (!selectedDataViewNotFound && dataViewId) {
setSelectedOption([
{ id: kibanaDataViews[dataViewId].id, label: kibanaDataViews[dataViewId].title },
]);
const dataViewsTitle = kibanaDataViews[dataViewId].title;
const dataViewsId = kibanaDataViews[dataViewId].id;

setShowDataViewAlertsOnAlertsWarning(dataViewsId === 'security-solution-default');

setSelectedOption([{ id: dataViewsId, label: dataViewsTitle }]);
} else {
setSelectedOption([]);
}
}, [dataViewId, field, kibanaDataViews, selectedDataViewNotFound]);
}, [
dataViewId,
field,
kibanaDataViews,
selectedDataViewNotFound,
setShowDataViewAlertsOnAlertsWarning,
]);

// TODO: optimize this, pass down array of data view ids
// at the same time we grab the data views in the top level form component
Expand All @@ -76,7 +88,6 @@ export const DataViewSelector = ({ kibanaDataViews, field }: DataViewSelectorPro

const onChangeDataViews = (options: Array<EuiComboBoxOptionOption<string>>) => {
const selectedDataViewOption = options;

setSelectedOption(selectedDataViewOption ?? []);

if (
Expand Down Expand Up @@ -105,6 +116,19 @@ export const DataViewSelector = ({ kibanaDataViews, field }: DataViewSelectorPro
<EuiSpacer size="s" />
</>
)}
{showDataViewAlertsOnAlertsWarning && (
<>
<EuiCallOut
title={i18n.DDATA_VIEW_ALERTS_ON_ALERTS_WARNING_LABEL}
color="warning"
iconType="help"
data-test-subj="defaultSecurityDataViewWarning"
>
<p>{i18n.DATA_VIEW_ALERTS_ON_ALERTS_WARNING_DESCRIPTION}</p>
</EuiCallOut>
<EuiSpacer size="s" />
</>
)}
<EuiFormRow
label={field?.label}
helpText={field?.helpText}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,18 @@ export const DATA_VIEW_NOT_FOUND_WARNING_DESCRIPTION = (dataView: string) =>
'Your data view of "id": "{dataView}" was not found. It could be that it has since been deleted.',
}
);

export const DDATA_VIEW_ALERTS_ON_ALERTS_WARNING_LABEL = i18n.translate(
'xpack.securitySolution.detectionEngine.stepDefineRule.dataViewIncludesAlertsIndexLabel',
{
defaultMessage: 'Default Security data view',
}
);

export const DATA_VIEW_ALERTS_ON_ALERTS_WARNING_DESCRIPTION = i18n.translate(
'xpack.securitySolution.detectionEngine.stepDefineRule.dataViewIncludesAlertsIndexDescription',
{
defaultMessage:
'The default Security data view includes the alerts index. This could result in redundant alerts being generated from existing alerts.',
}
);

0 comments on commit b406632

Please sign in to comment.