mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Security Solution] expandable flyout - fix prevalence query not taking into account fields with multiple values (#166891)
This commit is contained in:
parent
7b4e6a6775
commit
af51e26333
8 changed files with 87 additions and 42 deletions
|
@ -79,7 +79,7 @@ describe('PrevalenceDetails', () => {
|
|||
data: [
|
||||
{
|
||||
field: field1,
|
||||
value: 'value1',
|
||||
values: ['value1'],
|
||||
alertCount: 1,
|
||||
docCount: 1,
|
||||
hostPrevalence: 0.05,
|
||||
|
@ -87,7 +87,7 @@ describe('PrevalenceDetails', () => {
|
|||
},
|
||||
{
|
||||
field: field2,
|
||||
value: 'value2',
|
||||
values: ['value2'],
|
||||
alertCount: 1,
|
||||
docCount: 1,
|
||||
hostPrevalence: 0.5,
|
||||
|
@ -124,7 +124,7 @@ describe('PrevalenceDetails', () => {
|
|||
data: [
|
||||
{
|
||||
field: 'field1',
|
||||
value: 'value1',
|
||||
values: ['value1'],
|
||||
alertCount: 1000,
|
||||
docCount: 2000000,
|
||||
hostPrevalence: 0.05,
|
||||
|
@ -154,6 +154,35 @@ describe('PrevalenceDetails', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('should render multiple values in value column', () => {
|
||||
(usePrevalence as jest.Mock).mockReturnValue({
|
||||
loading: false,
|
||||
error: false,
|
||||
data: [
|
||||
{
|
||||
field: 'field1',
|
||||
values: ['value1', 'value2'],
|
||||
alertCount: 1000,
|
||||
docCount: 2000000,
|
||||
hostPrevalence: 0.05,
|
||||
userPrevalence: 0.1,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const { getByTestId } = render(
|
||||
<TestProviders>
|
||||
<LeftPanelContext.Provider value={panelContextValue}>
|
||||
<PrevalenceDetails />
|
||||
</LeftPanelContext.Provider>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
expect(getByTestId(PREVALENCE_DETAILS_TABLE_TEST_ID)).toBeInTheDocument();
|
||||
expect(getByTestId(PREVALENCE_DETAILS_TABLE_VALUE_CELL_TEST_ID)).toHaveTextContent('value1');
|
||||
expect(getByTestId(PREVALENCE_DETAILS_TABLE_VALUE_CELL_TEST_ID)).toHaveTextContent('value2');
|
||||
});
|
||||
|
||||
it('should render the table with only basic columns if license is not platinum', () => {
|
||||
const field1 = 'field1';
|
||||
const field2 = 'field2';
|
||||
|
@ -163,7 +192,7 @@ describe('PrevalenceDetails', () => {
|
|||
data: [
|
||||
{
|
||||
field: field1,
|
||||
value: 'value1',
|
||||
values: ['value1'],
|
||||
alertCount: 1,
|
||||
docCount: 1,
|
||||
hostPrevalence: 0.05,
|
||||
|
@ -171,7 +200,7 @@ describe('PrevalenceDetails', () => {
|
|||
},
|
||||
{
|
||||
field: field2,
|
||||
value: 'value2',
|
||||
values: ['value2'],
|
||||
alertCount: 1,
|
||||
docCount: 1,
|
||||
hostPrevalence: 0.5,
|
||||
|
|
|
@ -74,7 +74,7 @@ const columns: Array<EuiBasicTableColumn<PrevalenceDetailsRow>> = [
|
|||
width: '20%',
|
||||
},
|
||||
{
|
||||
field: 'value',
|
||||
field: 'values',
|
||||
name: (
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.flyout.left.insights.prevalence.valueColumnLabel"
|
||||
|
@ -82,7 +82,15 @@ const columns: Array<EuiBasicTableColumn<PrevalenceDetailsRow>> = [
|
|||
/>
|
||||
),
|
||||
'data-test-subj': PREVALENCE_DETAILS_TABLE_VALUE_CELL_TEST_ID,
|
||||
render: (value: string) => <EuiText size="xs">{value}</EuiText>,
|
||||
render: (values: string[]) => (
|
||||
<EuiFlexGroup direction="column" gutterSize="none">
|
||||
{values.map((value) => (
|
||||
<EuiFlexItem key={value}>
|
||||
<EuiText size="xs">{value}</EuiText>
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
width: '20%',
|
||||
},
|
||||
{
|
||||
|
@ -113,9 +121,9 @@ const columns: Array<EuiBasicTableColumn<PrevalenceDetailsRow>> = [
|
|||
),
|
||||
'data-test-subj': PREVALENCE_DETAILS_TABLE_ALERT_COUNT_CELL_TEST_ID,
|
||||
render: (data: PrevalenceDetailsRow) => {
|
||||
const dataProviders = [
|
||||
getDataProvider(data.field, `timeline-indicator-${data.field}-${data.value}`, data.value),
|
||||
];
|
||||
const dataProviders = data.values.map((value) =>
|
||||
getDataProvider(data.field, `timeline-indicator-${data.field}-${value}`, value)
|
||||
);
|
||||
return data.alertCount > 0 ? (
|
||||
<InvestigateInTimelineButton
|
||||
asEmptyButton={true}
|
||||
|
@ -159,24 +167,18 @@ const columns: Array<EuiBasicTableColumn<PrevalenceDetailsRow>> = [
|
|||
),
|
||||
'data-test-subj': PREVALENCE_DETAILS_TABLE_DOC_COUNT_CELL_TEST_ID,
|
||||
render: (data: PrevalenceDetailsRow) => {
|
||||
const dataProviders = [
|
||||
{
|
||||
...getDataProvider(
|
||||
data.field,
|
||||
`timeline-indicator-${data.field}-${data.value}`,
|
||||
data.value
|
||||
const dataProviders = data.values.map((value) => ({
|
||||
...getDataProvider(data.field, `timeline-indicator-${data.field}-${value}`, value),
|
||||
and: [
|
||||
getDataProviderAnd(
|
||||
'event.kind',
|
||||
`timeline-indicator-event.kind-not-signal`,
|
||||
'signal',
|
||||
IS_OPERATOR,
|
||||
true
|
||||
),
|
||||
and: [
|
||||
getDataProviderAnd(
|
||||
'event.kind',
|
||||
`timeline-indicator-event.kind-not-signal`,
|
||||
'signal',
|
||||
IS_OPERATOR,
|
||||
true
|
||||
),
|
||||
],
|
||||
},
|
||||
];
|
||||
],
|
||||
}));
|
||||
return data.docCount > 0 ? (
|
||||
<InvestigateInTimelineButton
|
||||
asEmptyButton={true}
|
||||
|
|
|
@ -91,13 +91,14 @@ describe('<PrevalenceOverview />', () => {
|
|||
it('should render only data with prevalence less than 10%', () => {
|
||||
const field1 = 'field1';
|
||||
const field2 = 'field2';
|
||||
const field3 = 'field3';
|
||||
(usePrevalence as jest.Mock).mockReturnValue({
|
||||
loading: false,
|
||||
error: false,
|
||||
data: [
|
||||
{
|
||||
field: field1,
|
||||
value: 'value1',
|
||||
values: ['value1'],
|
||||
alertCount: 1,
|
||||
docCount: 1,
|
||||
hostPrevalence: 0.05,
|
||||
|
@ -105,7 +106,15 @@ describe('<PrevalenceOverview />', () => {
|
|||
},
|
||||
{
|
||||
field: field2,
|
||||
value: 'value2',
|
||||
values: ['value2', 'value22'],
|
||||
alertCount: 1,
|
||||
docCount: 1,
|
||||
hostPrevalence: 0.06,
|
||||
userPrevalence: 0.2,
|
||||
},
|
||||
{
|
||||
field: field3,
|
||||
values: ['value3'],
|
||||
alertCount: 1,
|
||||
docCount: 1,
|
||||
hostPrevalence: 0.5,
|
||||
|
@ -126,8 +135,14 @@ describe('<PrevalenceOverview />', () => {
|
|||
|
||||
const iconDataTestSubj2 = `${PREVALENCE_TEST_ID}${field2}Icon`;
|
||||
const valueDataTestSubj2 = `${PREVALENCE_TEST_ID}${field2}Value`;
|
||||
expect(queryByTestId(iconDataTestSubj2)).not.toBeInTheDocument();
|
||||
expect(queryByTestId(valueDataTestSubj2)).not.toBeInTheDocument();
|
||||
expect(getByTestId(iconDataTestSubj2)).toBeInTheDocument();
|
||||
expect(getByTestId(valueDataTestSubj2)).toBeInTheDocument();
|
||||
expect(getByTestId(valueDataTestSubj2)).toHaveTextContent('field2, value2,value22 is uncommon');
|
||||
|
||||
const iconDataTestSubj3 = `${PREVALENCE_TEST_ID}${field3}Icon`;
|
||||
const valueDataTestSubj3 = `${PREVALENCE_TEST_ID}${field3}Value`;
|
||||
expect(queryByTestId(iconDataTestSubj3)).not.toBeInTheDocument();
|
||||
expect(queryByTestId(valueDataTestSubj3)).not.toBeInTheDocument();
|
||||
|
||||
expect(queryByText(NO_DATA_MESSAGE)).not.toBeInTheDocument();
|
||||
});
|
||||
|
@ -139,7 +154,7 @@ describe('<PrevalenceOverview />', () => {
|
|||
data: [
|
||||
{
|
||||
field: 'field1',
|
||||
value: 'value1',
|
||||
values: ['value1'],
|
||||
alertCount: 1,
|
||||
docCount: 1,
|
||||
hostPrevalence: 0.05,
|
||||
|
|
|
@ -99,7 +99,7 @@ export const PrevalenceOverview: FC = () => {
|
|||
<FormattedMessage
|
||||
id="xpack.securitySolution.flyout.right.insights.prevalence.rowDescription"
|
||||
defaultMessage="{field}, {value} is uncommon"
|
||||
values={{ field: d.field, value: d.value }}
|
||||
values={{ field: d.field, value: d.values.toString() }}
|
||||
/>
|
||||
}
|
||||
data-test-subj={`${PREVALENCE_TEST_ID}${d.field}`}
|
||||
|
|
|
@ -124,7 +124,7 @@ describe('usePrevalence', () => {
|
|||
expect(hookResult.result.current.data).toEqual([
|
||||
{
|
||||
field: 'host.name',
|
||||
value: 'host-1',
|
||||
values: ['host-1'],
|
||||
alertCount: 1,
|
||||
docCount: 1,
|
||||
hostPrevalence: 0.1,
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common';
|
||||
import { isArray } from 'lodash/fp';
|
||||
import { useMemo } from 'react';
|
||||
import { useHighlightedFields } from './use_highlighted_fields';
|
||||
import { convertHighlightedFieldsToPrevalenceFilters } from '../utils/highlighted_fields_helpers';
|
||||
|
@ -24,7 +23,7 @@ import { EventKind } from '../constants/event_kinds';
|
|||
|
||||
export interface PrevalenceData {
|
||||
field: string;
|
||||
value: string;
|
||||
values: string[];
|
||||
alertCount: number;
|
||||
docCount: number;
|
||||
hostPrevalence: number;
|
||||
|
@ -91,7 +90,7 @@ export const usePrevalence = ({
|
|||
const fieldNames = Object.keys(data.aggregations[FIELD_NAMES_AGG_KEY].buckets);
|
||||
|
||||
fieldNames.forEach((fieldName: string) => {
|
||||
const fieldValue = highlightedFields[fieldName].values;
|
||||
const fieldValues = highlightedFields[fieldName].values;
|
||||
|
||||
// retrieves the number of signals for the current field/value pair
|
||||
const alertCount =
|
||||
|
@ -131,7 +130,7 @@ export const usePrevalence = ({
|
|||
|
||||
items.push({
|
||||
field: fieldName,
|
||||
value: isArray(fieldValue) ? fieldValue[0] : fieldValue,
|
||||
values: fieldValues,
|
||||
alertCount,
|
||||
docCount,
|
||||
hostPrevalence,
|
||||
|
|
|
@ -58,12 +58,12 @@ describe('convertHighlightedFieldsToPrevalenceFilters', () => {
|
|||
values: ['host-1'],
|
||||
},
|
||||
'user.name': {
|
||||
values: ['user-1'],
|
||||
values: ['user-1', 'user-2'],
|
||||
},
|
||||
};
|
||||
expect(convertHighlightedFieldsToPrevalenceFilters(highlightedFields)).toEqual({
|
||||
'host.name': { match: { 'host.name': 'host-1' } },
|
||||
'user.name': { match: { 'user.name': 'user-1' } },
|
||||
'host.name': { terms: { 'host.name': ['host-1'] } },
|
||||
'user.name': { terms: { 'user.name': ['user-1', 'user-2'] } },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -48,7 +48,7 @@ export const convertHighlightedFieldsToPrevalenceFilters = (
|
|||
|
||||
return {
|
||||
...acc,
|
||||
[curr]: { match: { [curr]: Array.isArray(values) ? values[0] : values } },
|
||||
[curr]: { terms: { [curr]: values } },
|
||||
};
|
||||
}, []) as unknown as Record<string, QueryDslQueryContainer>;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue