mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[8.12] [sentinel_one] Fix agent status field name in Alert details highlighted fields (#174421) (#174802)
# Backport This will backport the following commits from `main` to `8.12`: - [[sentinel_one] Fix agent status field name in Alert details highlighted fields (#174421)](https://github.com/elastic/kibana/pull/174421) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Patryk Kopyciński","email":"contact@patrykkopycinski.com"},"sourceCommit":{"committedDate":"2024-01-12T23:03:06Z","message":"[sentinel_one] Fix agent status field name in Alert details highlighted fields (#174421)\n\n## Summary\r\n\r\nFixes https://github.com/elastic/kibana/issues/174235\r\n\r\n<img width=\"1809\" alt=\"image\"\r\nsrc=\"43f120c7
-8bbd-4e5a-9824-5db4fda9f35c\">","sha":"5344f86769536b901c19d6ce894c5b614a3836ac","branchLabelMapping":{"^v8.13.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","release_note:skip","v8.12.1","v8.13.0"],"title":"[sentinel_one] Fix agent status field name in Alert details highlighted fields","number":174421,"url":"https://github.com/elastic/kibana/pull/174421","mergeCommit":{"message":"[sentinel_one] Fix agent status field name in Alert details highlighted fields (#174421)\n\n## Summary\r\n\r\nFixes https://github.com/elastic/kibana/issues/174235\r\n\r\n<img width=\"1809\" alt=\"image\"\r\nsrc=\"43f120c7
-8bbd-4e5a-9824-5db4fda9f35c\">","sha":"5344f86769536b901c19d6ce894c5b614a3836ac"}},"sourceBranch":"main","suggestedTargetBranches":["8.12"],"targetPullRequestStates":[{"branch":"8.12","label":"v8.12.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.13.0","branchLabelMappingKey":"^v8.13.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/174421","number":174421,"mergeCommit":{"message":"[sentinel_one] Fix agent status field name in Alert details highlighted fields (#174421)\n\n## Summary\r\n\r\nFixes https://github.com/elastic/kibana/issues/174235\r\n\r\n<img width=\"1809\" alt=\"image\"\r\nsrc=\"43f120c7
-8bbd-4e5a-9824-5db4fda9f35c\">","sha":"5344f86769536b901c19d6ce894c5b614a3836ac"}}]}] BACKPORT--> Co-authored-by: Patryk Kopyciński <contact@patrykkopycinski.com>
This commit is contained in:
parent
5562e22825
commit
68739f97f7
10 changed files with 170 additions and 6 deletions
|
@ -52,6 +52,7 @@ const alwaysDisplayedFields: EventSummaryField[] = [
|
|||
{ id: 'agent.id', overrideField: AGENT_STATUS_FIELD_NAME, label: i18n.AGENT_STATUS },
|
||||
{
|
||||
id: SENTINEL_ONE_AGENT_ID_FIELD,
|
||||
overrideField: AGENT_STATUS_FIELD_NAME,
|
||||
label: i18n.AGENT_STATUS,
|
||||
},
|
||||
// ** //
|
||||
|
|
|
@ -1777,6 +1777,7 @@ describe('Exception helpers', () => {
|
|||
},
|
||||
{
|
||||
id: 'observer.serial_number',
|
||||
overrideField: 'agent.status',
|
||||
label: 'Agent status',
|
||||
},
|
||||
{
|
||||
|
@ -1801,6 +1802,7 @@ describe('Exception helpers', () => {
|
|||
},
|
||||
{
|
||||
id: 'observer.serial_number',
|
||||
overrideField: 'agent.status',
|
||||
label: 'Agent status',
|
||||
},
|
||||
{
|
||||
|
|
|
@ -45,7 +45,7 @@ const EuiFlexGroupStyled = styled(EuiFlexGroup)`
|
|||
`;
|
||||
|
||||
export const SentinelOneAgentStatus = React.memo(
|
||||
({ agentId, dataTestSubj }: { agentId: string; dataTestSubj?: string }) => {
|
||||
({ agentId, 'data-test-subj': dataTestSubj }: { agentId: string; 'data-test-subj'?: string }) => {
|
||||
const { data, isFetched } = useSentinelOneAgentData({ agentId });
|
||||
|
||||
const label = useMemo(() => {
|
||||
|
|
|
@ -35,6 +35,10 @@ export interface HighlightedFieldsTableRow {
|
|||
* Highlighted field name (overrideField or if null, falls back to id)
|
||||
*/
|
||||
field: string;
|
||||
/**
|
||||
* Highlighted field's original name, when the field is overridden
|
||||
*/
|
||||
originalField?: string;
|
||||
/**
|
||||
* Highlighted field value
|
||||
*/
|
||||
|
@ -74,6 +78,7 @@ const columns: Array<EuiBasicTableColumn<HighlightedFieldsTableRow>> = [
|
|||
width: '70%',
|
||||
render: (description: {
|
||||
field: string;
|
||||
originalField?: string;
|
||||
values: string[] | null | undefined;
|
||||
scopeId: string;
|
||||
isPreview: boolean;
|
||||
|
@ -94,7 +99,11 @@ const columns: Array<EuiBasicTableColumn<HighlightedFieldsTableRow>> = [
|
|||
: []
|
||||
}
|
||||
>
|
||||
<HighlightedFieldsCell values={description.values} field={description.field} />
|
||||
<HighlightedFieldsCell
|
||||
values={description.values}
|
||||
field={description.field}
|
||||
originalField={description.originalField}
|
||||
/>
|
||||
</SecurityCellActions>
|
||||
),
|
||||
},
|
||||
|
|
|
@ -20,8 +20,10 @@ import { LeftPanelInsightsTab, DocumentDetailsLeftPanelKey } from '../../left';
|
|||
import { TestProviders } from '../../../../common/mock';
|
||||
import { ENTITIES_TAB_ID } from '../../left/components/entities_details';
|
||||
import { useGetEndpointDetails } from '../../../../management/hooks';
|
||||
import { useSentinelOneAgentData } from '../../../../detections/components/host_isolation/use_sentinelone_host_isolation';
|
||||
|
||||
jest.mock('../../../../management/hooks');
|
||||
jest.mock('../../../../detections/components/host_isolation/use_sentinelone_host_isolation');
|
||||
|
||||
const flyoutContextValue = {
|
||||
openLeftPanel: jest.fn(),
|
||||
|
@ -86,7 +88,22 @@ describe('<HighlightedFieldsCell />', () => {
|
|||
expect(getByTestId(HIGHLIGHTED_FIELDS_AGENT_STATUS_CELL_TEST_ID)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render agent status component if override field is agent.status', () => {
|
||||
it('should render sentinelone agent status cell if field is agent.status and origialField is observer.serial_number', () => {
|
||||
(useSentinelOneAgentData as jest.Mock).mockReturnValue({ isFetched: true });
|
||||
const { getByTestId } = render(
|
||||
<TestProviders>
|
||||
<HighlightedFieldsCell
|
||||
values={['value']}
|
||||
field={'agent.status'}
|
||||
originalField="observer.serial_number"
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
expect(getByTestId(HIGHLIGHTED_FIELDS_AGENT_STATUS_CELL_TEST_ID)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not render if values is null', () => {
|
||||
const { container } = render(<HighlightedFieldsCell values={null} field={'field'} />);
|
||||
|
||||
expect(container).toBeEmptyDOMElement();
|
||||
|
|
|
@ -66,6 +66,10 @@ export interface HighlightedFieldsCellProps {
|
|||
* Highlighted field's name used to know what component to display
|
||||
*/
|
||||
field: string;
|
||||
/**
|
||||
* Highlighted field's original name, when the field is overridden
|
||||
*/
|
||||
originalField?: string;
|
||||
/**
|
||||
* Highlighted field's value to display
|
||||
*/
|
||||
|
@ -75,7 +79,11 @@ export interface HighlightedFieldsCellProps {
|
|||
/**
|
||||
* Renders a component in the highlighted fields table cell based on the field name
|
||||
*/
|
||||
export const HighlightedFieldsCell: VFC<HighlightedFieldsCellProps> = ({ values, field }) => (
|
||||
export const HighlightedFieldsCell: VFC<HighlightedFieldsCellProps> = ({
|
||||
values,
|
||||
field,
|
||||
originalField,
|
||||
}) => (
|
||||
<>
|
||||
{values != null &&
|
||||
values.map((value, i) => {
|
||||
|
@ -87,13 +95,17 @@ export const HighlightedFieldsCell: VFC<HighlightedFieldsCellProps> = ({ values,
|
|||
>
|
||||
{field === HOST_NAME_FIELD_NAME || field === USER_NAME_FIELD_NAME ? (
|
||||
<LinkFieldCell value={value} />
|
||||
) : field === AGENT_STATUS_FIELD_NAME &&
|
||||
originalField === SENTINEL_ONE_AGENT_ID_FIELD ? (
|
||||
<SentinelOneAgentStatus
|
||||
agentId={String(value ?? '')}
|
||||
data-test-subj={HIGHLIGHTED_FIELDS_AGENT_STATUS_CELL_TEST_ID}
|
||||
/>
|
||||
) : field === AGENT_STATUS_FIELD_NAME ? (
|
||||
<EndpointAgentStatusById
|
||||
endpointAgentId={String(value ?? '')}
|
||||
data-test-subj={HIGHLIGHTED_FIELDS_AGENT_STATUS_CELL_TEST_ID}
|
||||
/>
|
||||
) : field === SENTINEL_ONE_AGENT_ID_FIELD ? (
|
||||
<SentinelOneAgentStatus agentId={String(value ?? '')} />
|
||||
) : (
|
||||
<span data-test-subj={HIGHLIGHTED_FIELDS_BASIC_CELL_TEST_ID}>{value}</span>
|
||||
)}
|
||||
|
|
|
@ -9,6 +9,7 @@ import { renderHook } from '@testing-library/react-hooks';
|
|||
|
||||
import { mockDataFormattedForFieldBrowser } from '../mocks/mock_data_formatted_for_field_browser';
|
||||
import { useHighlightedFields } from './use_highlighted_fields';
|
||||
import { SENTINEL_ONE_AGENT_ID_FIELD } from '../../../../common/utils/sentinelone_alert_check';
|
||||
|
||||
const dataFormattedForFieldBrowser = mockDataFormattedForFieldBrowser;
|
||||
|
||||
|
@ -21,4 +22,112 @@ describe('useHighlightedFields', () => {
|
|||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should omit endpoint agent id field if data is not s1 alert', () => {
|
||||
const hookResult = renderHook(() =>
|
||||
useHighlightedFields({
|
||||
dataFormattedForFieldBrowser: dataFormattedForFieldBrowser.concat({
|
||||
category: 'agent',
|
||||
field: 'agent.id',
|
||||
values: ['deb35a20-70f8-458e-a64a-c9e6f7575893'],
|
||||
originalValue: ['deb35a20-70f8-458e-a64a-c9e6f7575893'],
|
||||
isObjectArray: false,
|
||||
}),
|
||||
investigationFields: ['agent.status', 'agent.id'],
|
||||
})
|
||||
);
|
||||
|
||||
expect(hookResult.result.current).toEqual({
|
||||
'kibana.alert.rule.type': {
|
||||
values: ['query'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should return endpoint agent id field if data is s1 alert', () => {
|
||||
const hookResult = renderHook(() =>
|
||||
useHighlightedFields({
|
||||
dataFormattedForFieldBrowser: dataFormattedForFieldBrowser.concat([
|
||||
{
|
||||
category: 'agent',
|
||||
field: 'agent.type',
|
||||
values: ['endpoint'],
|
||||
originalValue: ['endpoint'],
|
||||
isObjectArray: false,
|
||||
},
|
||||
{
|
||||
category: 'agent',
|
||||
field: 'agent.id',
|
||||
values: ['deb35a20-70f8-458e-a64a-c9e6f7575893'],
|
||||
originalValue: ['deb35a20-70f8-458e-a64a-c9e6f7575893'],
|
||||
isObjectArray: false,
|
||||
},
|
||||
]),
|
||||
investigationFields: ['agent.status', 'agent.id'],
|
||||
})
|
||||
);
|
||||
|
||||
expect(hookResult.result.current).toEqual({
|
||||
'kibana.alert.rule.type': {
|
||||
values: ['query'],
|
||||
},
|
||||
'agent.id': {
|
||||
values: ['deb35a20-70f8-458e-a64a-c9e6f7575893'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should omit sentinelone agent id field if data is not s1 alert', () => {
|
||||
const hookResult = renderHook(() =>
|
||||
useHighlightedFields({
|
||||
dataFormattedForFieldBrowser: dataFormattedForFieldBrowser.concat({
|
||||
category: 'observer',
|
||||
field: `observer.${SENTINEL_ONE_AGENT_ID_FIELD}`,
|
||||
values: ['deb35a20-70f8-458e-a64a-c9e6f7575893'],
|
||||
originalValue: ['deb35a20-70f8-458e-a64a-c9e6f7575893'],
|
||||
isObjectArray: false,
|
||||
}),
|
||||
investigationFields: ['agent.status', 'observer.serial_number'],
|
||||
})
|
||||
);
|
||||
|
||||
expect(hookResult.result.current).toEqual({
|
||||
'kibana.alert.rule.type': {
|
||||
values: ['query'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should return sentinelone agent id field if data is s1 alert', () => {
|
||||
const hookResult = renderHook(() =>
|
||||
useHighlightedFields({
|
||||
dataFormattedForFieldBrowser: dataFormattedForFieldBrowser.concat([
|
||||
{
|
||||
category: 'event',
|
||||
field: 'event.module',
|
||||
values: ['sentinel_one'],
|
||||
originalValue: ['sentinel_one'],
|
||||
isObjectArray: false,
|
||||
},
|
||||
{
|
||||
category: 'observer',
|
||||
field: SENTINEL_ONE_AGENT_ID_FIELD,
|
||||
values: ['deb35a20-70f8-458e-a64a-c9e6f7575893'],
|
||||
originalValue: ['deb35a20-70f8-458e-a64a-c9e6f7575893'],
|
||||
isObjectArray: false,
|
||||
},
|
||||
]),
|
||||
investigationFields: ['agent.status', 'observer.serial_number'],
|
||||
})
|
||||
);
|
||||
|
||||
expect(hookResult.result.current).toEqual({
|
||||
'kibana.alert.rule.type': {
|
||||
values: ['query'],
|
||||
},
|
||||
'observer.serial_number': {
|
||||
values: ['deb35a20-70f8-458e-a64a-c9e6f7575893'],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common';
|
||||
import { find, isEmpty } from 'lodash/fp';
|
||||
import { ALERT_RULE_TYPE } from '@kbn/rule-data-utils';
|
||||
import {
|
||||
SENTINEL_ONE_AGENT_ID_FIELD,
|
||||
isAlertFromSentinelOneEvent,
|
||||
} from '../../../../common/utils/sentinelone_alert_check';
|
||||
import { isAlertFromEndpointEvent } from '../../../../common/utils/endpoint_alert_check';
|
||||
import {
|
||||
getEventCategoriesFromData,
|
||||
|
@ -99,6 +103,14 @@ export const useHighlightedFields = ({
|
|||
return acc;
|
||||
}
|
||||
|
||||
// if the field is observer.serial_number and the event is not a sentinel one event we skip it
|
||||
if (
|
||||
field.id === SENTINEL_ONE_AGENT_ID_FIELD &&
|
||||
!isAlertFromSentinelOneEvent({ data: dataFormattedForFieldBrowser })
|
||||
) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
return {
|
||||
...acc,
|
||||
[field.id]: {
|
||||
|
|
|
@ -45,6 +45,7 @@ describe('convertHighlightedFieldsToTableRow', () => {
|
|||
field: 'host.name-override',
|
||||
description: {
|
||||
field: 'host.name-override',
|
||||
originalField: 'host.name',
|
||||
values: ['host-1'],
|
||||
scopeId: 'scopeId',
|
||||
isPreview,
|
||||
|
|
|
@ -29,6 +29,7 @@ export const convertHighlightedFieldsToTableRow = (
|
|||
field,
|
||||
description: {
|
||||
field,
|
||||
...(overrideFieldName ? { originalField: fieldName } : {}),
|
||||
values,
|
||||
scopeId,
|
||||
isPreview,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue