Skip to content

Commit

Permalink
[SIEM] Fixes Host Details Events Table to only show events for specif…
Browse files Browse the repository at this point in the history
…ied Host (elastic#57388) (elastic#57407)

## Summary

Fixes an issue where the `Events Table` on the `Host Details` page would show all events instead of those for the specific host. Also adds tests to make sure this doesn't happen again 🙂 

Note: This will not interfere with any user-added queries/filters as those are added separately. 

##### Before / After (See Event count at bottom of image)
<img width="300" alt="Screen_Shot_2020-02-11_at_15_35_12" src="https://user-images.githubusercontent.com/2946766/74286988-2f6bbb80-4ce6-11ea-9ca2-35d4ae9ff3f2.png"> <img width="300" alt="Screen_Shot_2020-02-11_at_15_46_23" src="https://user-images.githubusercontent.com/2946766/74287150-840f3680-4ce6-11ea-9267-365753a52fc2.png">



### Checklist

Delete any items that are not applicable to this PR.

- [ ] ~Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/master/packages/kbn-i18n/README.md)~
- [ ] ~[Documentation](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#writing-documentation) was added for features that require explanation or tutorials~
- [x] [Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios
- [ ] ~This was checked for [keyboard-only and screenreader accessibility](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Accessibility_testing_checklist)~
- [ ] ~This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)~
- [ ] ~This was checked for cross-browser compatibility, [including a check against IE11](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility)~

### For maintainers

- [ ] ~This was checked for breaking API changes and was [labeled appropriately](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#release-notes-process)~
  • Loading branch information
spong authored Feb 12, 2020
1 parent 9017c99 commit c340270
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import { MemoryRouter } from 'react-router-dom';
import { mockIndexPattern } from '../../../mock/index_pattern';
import { TestProviders } from '../../../mock/test_providers';
import { HostDetailsTabs } from './details_tabs';
import { SetAbsoluteRangeDatePicker } from './types';
import { HostDetailsTabsProps, SetAbsoluteRangeDatePicker } from './types';
import { hostDetailsPagePath } from '../types';
import { type } from './utils';
import { useMountAppended } from '../../../utils/use_mount_appended';
import { getHostDetailsPageFilters } from './helpers';

jest.mock('../../../containers/source', () => ({
indicesExistOrDataTemporarilyUnavailable: () => true,
Expand All @@ -41,6 +42,23 @@ describe('body', () => {
uncommonProcesses: 'UncommonProcessQueryTabBody',
anomalies: 'AnomaliesQueryTabBody',
events: 'EventsQueryTabBody',
alerts: 'HostAlertsQueryTabBody',
};

const mockHostDetailsPageFilters = getHostDetailsPageFilters('host-1');

const filterQuery = JSON.stringify({
bool: {
must: [],
filter: [{ match_all: {} }, { match_phrase: { 'host.name': { query: 'host-1' } } }],
should: [],
must_not: [],
},
});

const componentProps: Record<string, Partial<HostDetailsTabsProps>> = {
events: { pageFilters: mockHostDetailsPageFilters },
alerts: { pageFilters: mockHostDetailsPageFilters },
};
const mount = useMountAppended();

Expand All @@ -59,7 +77,8 @@ describe('body', () => {
hostDetailsPagePath={hostDetailsPagePath}
indexPattern={mockIndexPattern}
type={type}
filterQuery='{"bool":{"must":[],"filter":[{"match_all":{}},{"match_phrase":{"host.name":{"query":"host-1"}}}],"should":[],"must_not":[]}}'
pageFilters={mockHostDetailsPageFilters}
filterQuery={filterQuery}
/>
</MemoryRouter>
</TestProviders>
Expand All @@ -68,8 +87,7 @@ describe('body', () => {
// match against everything but the functions to ensure they are there as expected
expect(wrapper.find(componentName).props()).toMatchObject({
endDate: 0,
filterQuery:
'{"bool":{"must":[],"filter":[{"match_all":{}},{"match_phrase":{"host.name":{"query":"host-1"}}}],"should":[],"must_not":[]}}',
filterQuery,
skip: false,
startDate: 0,
type: 'details',
Expand All @@ -93,6 +111,7 @@ describe('body', () => {
title: 'filebeat-*,auditbeat-*,packetbeat-*',
},
hostName: 'host-1',
...(componentProps[path] != null ? componentProps[path] : []),
});
})
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ const HostDetailsTabs = React.memo<HostDetailsTabsProps>(
/>
<Route
path={`${hostDetailsPagePath}/:tabName(${HostsTableType.events})`}
render={() => <EventsQueryTabBody {...tabProps} />}
render={() => <EventsQueryTabBody {...tabProps} pageFilters={pageFilters} />}
/>
<Route
path={`${hostDetailsPagePath}/:tabName(${HostsTableType.alerts})`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { getHostDetailsEventsKqlQueryExpression } from './helpers';
import { getHostDetailsEventsKqlQueryExpression, getHostDetailsPageFilters } from './helpers';
import { esFilters } from '../../../../../../../../src/plugins/data/common/es_query';

describe('hosts page helpers', () => {
describe('getHostDetailsEventsKqlQueryExpression', () => {
Expand Down Expand Up @@ -35,4 +36,33 @@ describe('hosts page helpers', () => {
).toEqual('');
});
});

describe('getHostDetailsPageFilters', () => {
it('correctly constructs pageFilters for the given hostName', () => {
const expected: esFilters.Filter[] = [
{
meta: {
alias: null,
negate: false,
disabled: false,
type: 'phrase',
key: 'host.name',
value: 'host-1',
params: {
query: 'host-1',
},
},
query: {
match: {
'host.name': {
query: 'host-1',
type: 'phrase',
},
},
},
},
];
expect(getHostDetailsPageFilters('host-1')).toEqual(expected);
});
});
});
25 changes: 25 additions & 0 deletions x-pack/legacy/plugins/siem/public/pages/hosts/details/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

import { escapeQueryValue } from '../../../lib/keury';
import { esFilters } from '../../../../../../../../src/plugins/data/common/es_query';

/** Returns the kqlQueryExpression for the `Events` widget on the `Host Details` page */
export const getHostDetailsEventsKqlQueryExpression = ({
Expand All @@ -22,3 +23,27 @@ export const getHostDetailsEventsKqlQueryExpression = ({
return hostName.length ? `host.name: ${escapeQueryValue(hostName)}` : '';
}
};

export const getHostDetailsPageFilters = (hostName: string): esFilters.Filter[] => [
{
meta: {
alias: null,
negate: false,
disabled: false,
type: 'phrase',
key: 'host.name',
value: hostName,
params: {
query: hostName,
},
},
query: {
match: {
'host.name': {
query: hostName,
type: 'phrase',
},
},
},
},
];
30 changes: 6 additions & 24 deletions x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { EuiHorizontalRule, EuiSpacer } from '@elastic/eui';
import React, { useContext, useEffect, useCallback } from 'react';
import React, { useContext, useEffect, useCallback, useMemo } from 'react';
import { connect } from 'react-redux';
import { StickyContainer } from 'react-sticky';
import { compose } from 'redux';
Expand Down Expand Up @@ -41,6 +41,7 @@ import { HostDetailsTabs } from './details_tabs';
import { navTabsHostDetails } from './nav_tabs';
import { HostDetailsComponentProps, HostDetailsProps } from './types';
import { type } from './utils';
import { getHostDetailsPageFilters } from './helpers';

const HostOverviewManage = manageQuery(HostOverview);
const KpiHostDetailsManage = manageQuery(KpiHostsComponent);
Expand All @@ -64,29 +65,10 @@ const HostDetailsComponent = React.memo<HostDetailsComponentProps>(
}, [setHostDetailsTablesActivePageToZero, detailName]);
const capabilities = useContext(MlCapabilitiesContext);
const kibana = useKibana();
const hostDetailsPageFilters: esFilters.Filter[] = [
{
meta: {
alias: null,
negate: false,
disabled: false,
type: 'phrase',
key: 'host.name',
value: detailName,
params: {
query: detailName,
},
},
query: {
match: {
'host.name': {
query: detailName,
type: 'phrase',
},
},
},
},
];
const hostDetailsPageFilters: esFilters.Filter[] = useMemo(
() => getHostDetailsPageFilters(detailName),
[detailName]
);
const getFilters = () => [...hostDetailsPageFilters, ...filters];
const narrowDateRange = useCallback(
(min: number, max: number) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const EventsQueryTabBody = ({
deleteQuery,
endDate,
filterQuery,
pageFilters,
setQuery,
skip,
startDate,
Expand Down Expand Up @@ -73,6 +74,7 @@ export const EventsQueryTabBody = ({
end={endDate}
id={HOSTS_PAGE_TIMELINE_ID}
start={startDate}
pageFilters={pageFilters}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export interface QueryTabBodyProps {
export type HostsComponentsQueryProps = QueryTabBodyProps & {
deleteQuery?: ({ id }: { id: string }) => void;
indexPattern: IIndexPattern;
pageFilters?: esFilters.Filter[];
skip: boolean;
setQuery: SetQuery;
updateDateRange?: UpdateDateRange;
Expand Down

0 comments on commit c340270

Please sign in to comment.