diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts
index 8908adb42f202..d211a5914656b 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts
@@ -5,14 +5,14 @@
* 2.0.
*/
-import { ALERT_FLYOUT, CELL_TEXT, JSON_LINES, TABLE_ROWS } from '../../screens/alerts_details';
+import { ALERT_FLYOUT, CELL_TEXT, JSON_TEXT, TABLE_ROWS } from '../../screens/alerts_details';
import {
expandFirstAlert,
waitForAlertsIndexToBeCreated,
waitForAlertsPanelToBeLoaded,
} from '../../tasks/alerts';
-import { openJsonView, openTable, scrollJsonViewToBottom } from '../../tasks/alerts_details';
+import { openJsonView, openTable } from '../../tasks/alerts_details';
import { createCustomRuleActivated } from '../../tasks/api_calls/rules';
import { cleanKibana } from '../../tasks/common';
import { esArchiverLoad } from '../../tasks/es_archiver';
@@ -36,20 +36,14 @@ describe('Alert details with unmapped fields', () => {
});
it('Displays the unmapped field on the JSON view', () => {
- const expectedUnmappedField = { line: 2, text: ' "unmapped": "This is the unmapped field"' };
+ const expectedUnmappedValue = 'This is the unmapped field';
openJsonView();
- scrollJsonViewToBottom();
- cy.get(ALERT_FLYOUT)
- .find(JSON_LINES)
- .then((elements) => {
- const length = elements.length;
- cy.wrap(elements)
- .eq(length - expectedUnmappedField.line)
- .invoke('text')
- .should('include', expectedUnmappedField.text);
- });
+ cy.get(JSON_TEXT).then((x) => {
+ const parsed = JSON.parse(x.text());
+ expect(parsed._source.unmapped).to.equal(expectedUnmappedValue);
+ });
});
it('Displays the unmapped field on the table', () => {
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/cti_enrichments.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/cti_enrichments.spec.ts
index b3c6abcd8e426..f15e7adbbca44 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/cti_enrichments.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/cti_enrichments.spec.ts
@@ -10,7 +10,7 @@ import { cleanKibana, reload } from '../../tasks/common';
import { esArchiverLoad, esArchiverUnload } from '../../tasks/es_archiver';
import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login';
import {
- JSON_LINES,
+ JSON_TEXT,
TABLE_CELL,
TABLE_ROWS,
THREAT_DETAILS_VIEW,
@@ -28,11 +28,7 @@ import {
viewThreatIntelTab,
} from '../../tasks/alerts';
import { createCustomIndicatorRule } from '../../tasks/api_calls/rules';
-import {
- openJsonView,
- openThreatIndicatorDetails,
- scrollJsonViewToBottom,
-} from '../../tasks/alerts_details';
+import { openJsonView, openThreatIndicatorDetails } from '../../tasks/alerts_details';
import { ALERTS_URL } from '../../urls/navigation';
import { addsFieldsToTimeline } from '../../tasks/rule_details';
@@ -76,26 +72,39 @@ describe('CTI Enrichment', () => {
it('Displays persisted enrichments on the JSON view', () => {
const expectedEnrichment = [
- { line: 4, text: ' "threat": {' },
{
- line: 3,
- text: ' "enrichments": "{\\"indicator\\":{\\"first_seen\\":\\"2021-03-10T08:02:14.000Z\\",\\"file\\":{\\"size\\":80280,\\"pe\\":{},\\"type\\":\\"elf\\",\\"hash\\":{\\"sha256\\":\\"a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3\\",\\"tlsh\\":\\"6D7312E017B517CC1371A8353BED205E9128223972AE35302E97528DF957703BAB2DBE\\",\\"ssdeep\\":\\"1536:87vbq1lGAXSEYQjbChaAU2yU23M51DjZgSQAvcYkFtZTjzBht5:8D+CAXFYQChaAUk5ljnQssL\\",\\"md5\\":\\"9b6c3518a91d23ed77504b5416bfb5b3\\"}},\\"type\\":\\"file\\"},\\"matched\\":{\\"atomic\\":\\"a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3\\",\\"field\\":\\"myhash.mysha256\\",\\"id\\":\\"84cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f\\",\\"index\\":\\"logs-ti_abusech.malware\\",\\"type\\":\\"indicator_match_rule\\"}}"',
+ indicator: {
+ first_seen: '2021-03-10T08:02:14.000Z',
+ file: {
+ size: 80280,
+ pe: {},
+ type: 'elf',
+ hash: {
+ sha256: 'a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3',
+ tlsh: '6D7312E017B517CC1371A8353BED205E9128223972AE35302E97528DF957703BAB2DBE',
+ ssdeep:
+ '1536:87vbq1lGAXSEYQjbChaAU2yU23M51DjZgSQAvcYkFtZTjzBht5:8D+CAXFYQChaAUk5ljnQssL',
+ md5: '9b6c3518a91d23ed77504b5416bfb5b3',
+ },
+ },
+ type: 'file',
+ },
+ matched: {
+ atomic: 'a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3',
+ field: 'myhash.mysha256',
+ id: '84cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f',
+ index: 'logs-ti_abusech.malware',
+ type: 'indicator_match_rule',
+ },
},
- { line: 2, text: ' }' },
];
expandFirstAlert();
openJsonView();
- scrollJsonViewToBottom();
-
- cy.get(JSON_LINES).then((elements) => {
- const length = elements.length;
- expectedEnrichment.forEach((enrichment) => {
- cy.wrap(elements)
- .eq(length - enrichment.line)
- .invoke('text')
- .should('include', enrichment.text);
- });
+
+ cy.get(JSON_TEXT).then((x) => {
+ const parsed = JSON.parse(x.text());
+ expect(parsed._source.threat.enrichments).to.deep.equal(expectedEnrichment);
});
});
diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts b/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts
index c740a669d059a..584fba05452f0 100644
--- a/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts
+++ b/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts
@@ -28,6 +28,8 @@ export const JSON_LINES = '.euiCodeBlock__line';
export const JSON_VIEW_TAB = '[data-test-subj="jsonViewTab"]';
+export const JSON_TEXT = '[data-test-subj="jsonView"]';
+
export const TABLE_CELL = '.euiTableRowCell';
export const TABLE_TAB = '[data-test-subj="tableTab"]';
diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/alert_summary_view.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/alert_summary_view.test.tsx.snap
index d367c68586be1..930e1282ebca5 100644
--- a/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/alert_summary_view.test.tsx.snap
+++ b/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/alert_summary_view.test.tsx.snap
@@ -138,12 +138,17 @@ exports[`AlertSummaryView Behavior event code renders additional summary rows 1`
class="euiTableCellContent flyoutOverviewDescription euiTableCellContent--overflowingContent"
>
{
- "_id": "pEMaMmkBUV60JmNWmWVi",
- "_index": "filebeat-8.0.0-2019.02.19-000001",
+ "_index": ".ds-logs-endpoint.events.network-default-2021.09.28-000001",
+ "_id": "TUWyf3wBFCFU0qRJTauW",
"_score": 1,
- "_type": "_doc",
- "@timestamp": "2019-02-28T16:50:54.621Z",
- "agent": {
- "ephemeral_id": "9d391ef2-a734-4787-8891-67031178c641",
- "hostname": "siem-kibana",
- "id": "5de03d5f-52f3-482e-91d4-853c7de073c3",
- "type": "filebeat",
- "version": "8.0.0"
- },
- "cloud": {
- "availability_zone": "projects/189716325846/zones/us-east1-b",
- "instance": {
- "id": "5412578377715150143",
- "name": "siem-kibana"
+ "_source": {
+ "agent": {
+ "id": "2ac9e9b3-f6d5-4ce6-915d-8f1f8f413624",
+ "type": "endpoint",
+ "version": "8.0.0-SNAPSHOT"
},
- "machine": {
- "type": "projects/189716325846/machineTypes/n1-standard-1"
+ "process": {
+ "Ext": {
+ "ancestry": [
+ "MmFjOWU5YjMtZjZkNS00Y2U2LTkxNWQtOGYxZjhmNDEzNjI0LTIyMzY0LTEzMjc4NjA2NTAyLjA=",
+ "MmFjOWU5YjMtZjZkNS00Y2U2LTkxNWQtOGYxZjhmNDEzNjI0LTEtMTMyNzA3Njg2OTIuMA=="
+ ]
+ },
+ "name": "filebeat",
+ "pid": 22535,
+ "entity_id": "MmFjOWU5YjMtZjZkNS00Y2U2LTkxNWQtOGYxZjhmNDEzNjI0LTIyNTM1LTEzMjc4NjA2NTI4LjA=",
+ "executable": "/opt/Elastic/Agent/data/elastic-agent-058c40/install/filebeat-8.0.0-SNAPSHOT-linux-x86_64/filebeat"
},
- "project": {
- "id": "elastic-beats"
+ "destination": {
+ "address": "127.0.0.1",
+ "port": 9200,
+ "ip": "127.0.0.1"
},
- "provider": "gce"
- },
- "destination": {
- "bytes": 584,
- "ip": "10.47.8.200",
- "packets": 4,
- "port": 902
+ "source": {
+ "address": "127.0.0.1",
+ "port": 54146,
+ "ip": "127.0.0.1"
+ },
+ "message": "Endpoint network event",
+ "network": {
+ "transport": "tcp",
+ "type": "ipv4"
+ },
+ "@timestamp": "2021-10-14T16:45:58.0310772Z",
+ "ecs": {
+ "version": "1.11.0"
+ },
+ "data_stream": {
+ "namespace": "default",
+ "type": "logs",
+ "dataset": "endpoint.events.network"
+ },
+ "elastic": {
+ "agent": {
+ "id": "12345"
+ }
+ },
+ "host": {
+ "hostname": "test-linux-1",
+ "os": {
+ "Ext": {
+ "variant": "Debian"
+ },
+ "kernel": "4.19.0-17-cloud-amd64 #1 SMP Debian 4.19.194-2 (2021-06-21)",
+ "name": "Linux",
+ "family": "debian",
+ "type": "linux",
+ "version": "10",
+ "platform": "debian",
+ "full": "Debian 10"
+ },
+ "ip": [
+ "127.0.0.1",
+ "::1",
+ "10.1.2.3",
+ "2001:0DB8:AC10:FE01::"
+ ],
+ "name": "test-linux-1",
+ "id": "76ea303129f249aa7382338e4263eac1",
+ "mac": [
+ "aa:bb:cc:dd:ee:ff"
+ ],
+ "architecture": "x86_64"
+ },
+ "event": {
+ "agent_id_status": "verified",
+ "sequence": 44872,
+ "ingested": "2021-10-14T16:46:04Z",
+ "created": "2021-10-14T16:45:58.0310772Z",
+ "kind": "event",
+ "module": "endpoint",
+ "action": "connection_attempted",
+ "id": "MKPXftjGeHiQzUNj++++nn6R",
+ "category": [
+ "network"
+ ],
+ "type": [
+ "start"
+ ],
+ "dataset": "endpoint.events.network",
+ "outcome": "unknown"
+ },
+ "user": {
+ "Ext": {
+ "real": {
+ "name": "root",
+ "id": 0
+ }
+ },
+ "name": "root",
+ "id": 0
+ },
+ "group": {
+ "Ext": {
+ "real": {
+ "name": "root",
+ "id": 0
+ }
+ },
+ "name": "root",
+ "id": 0
+ }
},
- "event": {
- "kind": "event"
+ "fields": {
+ "host.os.full.text": [
+ "Debian 10"
+ ],
+ "event.category": [
+ "network"
+ ],
+ "process.name.text": [
+ "filebeat"
+ ],
+ "host.os.name.text": [
+ "Linux"
+ ],
+ "host.os.full": [
+ "Debian 10"
+ ],
+ "host.hostname": [
+ "test-linux-1"
+ ],
+ "process.pid": [
+ 22535
+ ],
+ "host.mac": [
+ "42:01:0a:c8:00:32"
+ ],
+ "elastic.agent.id": [
+ "abcdefg-f6d5-4ce6-915d-8f1f8f413624"
+ ],
+ "host.os.version": [
+ "10"
+ ],
+ "host.os.name": [
+ "Linux"
+ ],
+ "source.ip": [
+ "127.0.0.1"
+ ],
+ "destination.address": [
+ "127.0.0.1"
+ ],
+ "host.name": [
+ "test-linux-1"
+ ],
+ "event.agent_id_status": [
+ "verified"
+ ],
+ "event.kind": [
+ "event"
+ ],
+ "event.outcome": [
+ "unknown"
+ ],
+ "group.name": [
+ "root"
+ ],
+ "user.id": [
+ "0"
+ ],
+ "host.os.type": [
+ "linux"
+ ],
+ "process.Ext.ancestry": [
+ "MmFjOWU5YjMtZjZkNS00Y2U2LTkxNWQtOGYxZjhmNDEzNjI0LTIyMzY0LTEzMjc4NjA2NTAyLjA=",
+ "MmFjOWU5YjMtZjZkNS00Y2U2LTkxNWQtOGYxZjhmNDEzNjI0LTEtMTMyNzA3Njg2OTIuMA=="
+ ],
+ "user.Ext.real.id": [
+ "0"
+ ],
+ "data_stream.type": [
+ "logs"
+ ],
+ "host.architecture": [
+ "x86_64"
+ ],
+ "process.name": [
+ "filebeat"
+ ],
+ "agent.id": [
+ "2ac9e9b3-f6d5-4ce6-915d-8f1f8f413624"
+ ],
+ "source.port": [
+ 54146
+ ],
+ "ecs.version": [
+ "1.11.0"
+ ],
+ "event.created": [
+ "2021-10-14T16:45:58.031Z"
+ ],
+ "agent.version": [
+ "8.0.0-SNAPSHOT"
+ ],
+ "host.os.family": [
+ "debian"
+ ],
+ "destination.port": [
+ 9200
+ ],
+ "group.id": [
+ "0"
+ ],
+ "user.name": [
+ "root"
+ ],
+ "source.address": [
+ "127.0.0.1"
+ ],
+ "process.entity_id": [
+ "MmFjOWU5YjMtZjZkNS00Y2U2LTkxNWQtOGYxZjhmNDEzNjI0LTIyNTM1LTEzMjc4NjA2NTI4LjA="
+ ],
+ "host.ip": [
+ "127.0.0.1",
+ "::1",
+ "10.1.2.3",
+ "2001:0DB8:AC10:FE01::"
+ ],
+ "process.executable.caseless": [
+ "/opt/elastic/agent/data/elastic-agent-058c40/install/filebeat-8.0.0-snapshot-linux-x86_64/filebeat"
+ ],
+ "event.sequence": [
+ 44872
+ ],
+ "agent.type": [
+ "endpoint"
+ ],
+ "process.executable.text": [
+ "/opt/Elastic/Agent/data/elastic-agent-058c40/install/filebeat-8.0.0-SNAPSHOT-linux-x86_64/filebeat"
+ ],
+ "group.Ext.real.name": [
+ "root"
+ ],
+ "event.module": [
+ "endpoint"
+ ],
+ "host.os.kernel": [
+ "4.19.0-17-cloud-amd64 #1 SMP Debian 4.19.194-2 (2021-06-21)"
+ ],
+ "host.os.full.caseless": [
+ "debian 10"
+ ],
+ "host.id": [
+ "76ea303129f249aa7382338e4263eac1"
+ ],
+ "process.name.caseless": [
+ "filebeat"
+ ],
+ "network.type": [
+ "ipv4"
+ ],
+ "process.executable": [
+ "/opt/Elastic/Agent/data/elastic-agent-058c40/install/filebeat-8.0.0-SNAPSHOT-linux-x86_64/filebeat"
+ ],
+ "user.Ext.real.name": [
+ "root"
+ ],
+ "data_stream.namespace": [
+ "default"
+ ],
+ "message": [
+ "Endpoint network event"
+ ],
+ "destination.ip": [
+ "127.0.0.1"
+ ],
+ "network.transport": [
+ "tcp"
+ ],
+ "host.os.Ext.variant": [
+ "Debian"
+ ],
+ "group.Ext.real.id": [
+ "0"
+ ],
+ "event.ingested": [
+ "2021-10-14T16:46:04.000Z"
+ ],
+ "event.action": [
+ "connection_attempted"
+ ],
+ "@timestamp": [
+ "2021-10-14T16:45:58.031Z"
+ ],
+ "host.os.platform": [
+ "debian"
+ ],
+ "data_stream.dataset": [
+ "endpoint.events.network"
+ ],
+ "event.type": [
+ "start"
+ ],
+ "event.id": [
+ "MKPXftjGeHiQzUNj++++nn6R"
+ ],
+ "host.os.name.caseless": [
+ "linux"
+ ],
+ "event.dataset": [
+ "endpoint.events.network"
+ ],
+ "user.name.text": [
+ "root"
+ ]
}
}
diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx
index a8ba536a75541..37ca3b0b897a6 100644
--- a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx
@@ -11,7 +11,7 @@ import React from 'react';
import '../../mock/match_media';
import '../../mock/react_beautiful_dnd';
-import { mockDetailItemData, mockDetailItemDataId, TestProviders } from '../../mock';
+import { mockDetailItemData, mockDetailItemDataId, rawEventData, TestProviders } from '../../mock';
import { EventDetails, EventsViewType } from './event_details';
import { mockBrowserFields } from '../../containers/source/mock';
@@ -48,6 +48,7 @@ describe('EventDetails', () => {
timelineId: 'test',
eventView: EventsViewType.summaryView,
hostRisk: { fields: [], loading: true },
+ rawEventData,
};
const alertsProps = {
diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx
index e7092d9d6f466..a8305a635f157 100644
--- a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx
@@ -61,6 +61,7 @@ interface Props {
id: string;
isAlert: boolean;
isDraggable?: boolean;
+ rawEventData: object | undefined;
timelineTabType: TimelineTabs | 'flyout';
timelineId: string;
hostRisk: HostRisk | null;
@@ -106,6 +107,7 @@ const EventDetailsComponent: React.FC = ({
id,
isAlert,
isDraggable,
+ rawEventData,
timelineId,
timelineTabType,
hostRisk,
@@ -278,12 +280,12 @@ const EventDetailsComponent: React.FC = ({
<>
-
+
>
),
}),
- [data]
+ [rawEventData]
);
const tabs = useMemo(() => {
diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/json_view.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/json_view.test.tsx
index 696fac6016603..b20270266602d 100644
--- a/x-pack/plugins/security_solution/public/common/components/event_details/json_view.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/event_details/json_view.test.tsx
@@ -8,58 +8,15 @@
import { shallow } from 'enzyme';
import React from 'react';
-import { mockDetailItemData } from '../../mock';
+import { rawEventData } from '../../mock';
-import { buildJsonView, JsonView } from './json_view';
+import { JsonView } from './json_view';
describe('JSON View', () => {
describe('rendering', () => {
test('should match snapshot', () => {
- const wrapper = shallow();
+ const wrapper = shallow();
expect(wrapper).toMatchSnapshot();
});
});
-
- describe('buildJsonView', () => {
- test('should match a json', () => {
- const expectedData = {
- '@timestamp': '2019-02-28T16:50:54.621Z',
- _id: 'pEMaMmkBUV60JmNWmWVi',
- _index: 'filebeat-8.0.0-2019.02.19-000001',
- _score: 1,
- _type: '_doc',
- agent: {
- ephemeral_id: '9d391ef2-a734-4787-8891-67031178c641',
- hostname: 'siem-kibana',
- id: '5de03d5f-52f3-482e-91d4-853c7de073c3',
- type: 'filebeat',
- version: '8.0.0',
- },
- cloud: {
- availability_zone: 'projects/189716325846/zones/us-east1-b',
- instance: {
- id: '5412578377715150143',
- name: 'siem-kibana',
- },
- machine: {
- type: 'projects/189716325846/machineTypes/n1-standard-1',
- },
- project: {
- id: 'elastic-beats',
- },
- provider: 'gce',
- },
- destination: {
- bytes: 584,
- ip: '10.47.8.200',
- packets: 4,
- port: 902,
- },
- event: {
- kind: 'event',
- },
- };
- expect(buildJsonView(mockDetailItemData)).toEqual(expectedData);
- });
- });
});
diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/json_view.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/json_view.tsx
index 0614f131bcd10..0227d44f32305 100644
--- a/x-pack/plugins/security_solution/public/common/components/event_details/json_view.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/event_details/json_view.tsx
@@ -6,15 +6,13 @@
*/
import { EuiCodeBlock } from '@elastic/eui';
-import { set } from '@elastic/safer-lodash-set/fp';
import React, { useMemo } from 'react';
import styled from 'styled-components';
-import { TimelineEventsDetailsItem } from '../../../../common/search_strategy';
import { omitTypenameAndEmpty } from '../../../timelines/components/timeline/body/helpers';
interface Props {
- data: TimelineEventsDetailsItem[];
+ rawEventData: object | undefined;
}
const EuiCodeEditorContainer = styled.div`
@@ -23,15 +21,15 @@ const EuiCodeEditorContainer = styled.div`
}
`;
-export const JsonView = React.memo(({ data }) => {
+export const JsonView = React.memo(({ rawEventData }) => {
const value = useMemo(
() =>
JSON.stringify(
- buildJsonView(data),
+ rawEventData,
omitTypenameAndEmpty,
2 // indent level
),
- [data]
+ [rawEventData]
);
return (
@@ -50,16 +48,3 @@ export const JsonView = React.memo(({ data }) => {
});
JsonView.displayName = 'JsonView';
-
-export const buildJsonView = (data: TimelineEventsDetailsItem[]) =>
- data
- .sort((a, b) => a.field.localeCompare(b.field))
- .reduce(
- (accumulator, item) =>
- set(
- item.field,
- Array.isArray(item.originalValue) ? item.originalValue.join() : item.originalValue,
- accumulator
- ),
- {}
- );
diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/table/field_value_cell.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/table/field_value_cell.test.tsx
new file mode 100644
index 0000000000000..f6c43da2da8ac
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/common/components/event_details/table/field_value_cell.test.tsx
@@ -0,0 +1,193 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { render, screen } from '@testing-library/react';
+import React from 'react';
+
+import { BrowserField } from '../../../containers/source';
+import { FieldValueCell } from './field_value_cell';
+import { TestProviders } from '../../../mock';
+import { EventFieldsData } from '../types';
+
+const contextId = 'test';
+
+const eventId = 'TUWyf3wBFCFU0qRJTauW';
+
+const hostIpData: EventFieldsData = {
+ aggregatable: true,
+ ariaRowindex: 35,
+ category: 'host',
+ description: 'Host ip addresses.',
+ example: '127.0.0.1',
+ field: 'host.ip',
+ fields: {},
+ format: '',
+ indexes: ['auditbeat-*', 'filebeat-*', 'logs-*', 'winlogbeat-*'],
+ isObjectArray: false,
+ name: 'host.ip',
+ originalValue: ['127.0.0.1', '::1', '10.1.2.3', '2001:0DB8:AC10:FE01::'],
+ searchable: true,
+ type: 'ip',
+ values: ['127.0.0.1', '::1', '10.1.2.3', '2001:0DB8:AC10:FE01::'],
+};
+const hostIpValues = ['127.0.0.1', '::1', '10.1.2.3', 'fe80::4001:aff:fec8:32'];
+
+describe('FieldValueCell', () => {
+ describe('common behavior', () => {
+ beforeEach(() => {
+ render(
+
+
+
+ );
+ });
+
+ test('it formats multiple values such that each value is displayed on a single line', () => {
+ expect(screen.getByTestId(`event-field-${hostIpData.field}`)).toHaveClass(
+ 'euiFlexGroup--directionColumn'
+ );
+ });
+ });
+
+ describe('when `BrowserField` metadata is NOT available', () => {
+ beforeEach(() => {
+ render(
+
+
+
+ );
+ });
+
+ test('it renders each of the expected values when `fieldFromBrowserField` is undefined', () => {
+ hostIpValues.forEach((value) => {
+ expect(screen.getByText(value)).toBeInTheDocument();
+ });
+ });
+
+ test('it renders values formatted as plain text (without `eventFieldsTable__fieldValue` formatting)', () => {
+ expect(screen.getByTestId(`event-field-${hostIpData.field}`).firstChild).not.toHaveClass(
+ 'eventFieldsTable__fieldValue'
+ );
+ });
+ });
+
+ describe('`message` field formatting', () => {
+ const messageData: EventFieldsData = {
+ aggregatable: false,
+ ariaRowindex: 50,
+ category: 'base',
+ description:
+ 'For log events the message field contains the log message, optimized for viewing in a log viewer. For structured logs without an original message field, other fields can be concatenated to form a human-readable summary of the event. If multiple messages exist, they can be combined into one message.',
+ example: 'Hello World',
+ field: 'message',
+ fields: {},
+ format: '',
+ indexes: ['auditbeat-*', 'filebeat-*', 'logs-*', 'winlogbeat-*'],
+ isObjectArray: false,
+ name: 'message',
+ originalValue: ['Endpoint network event'],
+ searchable: true,
+ type: 'string',
+ values: ['Endpoint network event'],
+ };
+ const messageValues = ['Endpoint network event'];
+
+ const messageFieldFromBrowserField: BrowserField = {
+ aggregatable: false,
+ category: 'base',
+ description:
+ 'For log events the message field contains the log message, optimized for viewing in a log viewer. For structured logs without an original message field, other fields can be concatenated to form a human-readable summary of the event. If multiple messages exist, they can be combined into one message.',
+ example: 'Hello World',
+ fields: {},
+ format: '',
+ indexes: ['auditbeat-*', 'filebeat-*', 'logs-*', 'winlogbeat-*'],
+ name: 'message',
+ searchable: true,
+ type: 'string',
+ };
+
+ beforeEach(() => {
+ render(
+
+
+
+ );
+ });
+
+ test('it renders special formatting for the `message` field', () => {
+ expect(screen.getByTestId('event-field-message')).toBeInTheDocument();
+ });
+
+ test('it renders the expected message value', () => {
+ messageValues.forEach((value) => {
+ expect(screen.getByText(value)).toBeInTheDocument();
+ });
+ });
+ });
+
+ describe('when `BrowserField` metadata IS available', () => {
+ const hostIpFieldFromBrowserField: BrowserField = {
+ aggregatable: true,
+ category: 'host',
+ description: 'Host ip addresses.',
+ example: '127.0.0.1',
+ fields: {},
+ format: '',
+ indexes: ['auditbeat-*', 'filebeat-*', 'logs-*', 'winlogbeat-*'],
+ name: 'host.ip',
+ searchable: true,
+ type: 'ip',
+ };
+
+ beforeEach(() => {
+ render(
+
+
+
+ );
+ });
+
+ test('it renders values formatted with the expected class', () => {
+ expect(screen.getByTestId(`event-field-${hostIpData.field}`).firstChild).toHaveClass(
+ 'eventFieldsTable__fieldValue'
+ );
+ });
+
+ test('it renders link buttons for each of the host ip addresses', () => {
+ expect(screen.getAllByRole('button').length).toBe(hostIpValues.length);
+ });
+
+ test('it renders each of the expected values when `fieldFromBrowserField` is provided', () => {
+ hostIpValues.forEach((value) => {
+ expect(screen.getByText(value)).toBeInTheDocument();
+ });
+ });
+ });
+});
diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/table/field_value_cell.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/table/field_value_cell.tsx
index fc20f84d3650d..dc6c84b8138fe 100644
--- a/x-pack/plugins/security_solution/public/common/components/event_details/table/field_value_cell.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/event_details/table/field_value_cell.tsx
@@ -6,7 +6,7 @@
*/
import React from 'react';
-import { EuiText } from '@elastic/eui';
+import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
import { BrowserField } from '../../../containers/source';
import { OverflowField } from '../../tables/helpers';
import { FormattedFieldValue } from '../../../../timelines/components/timeline/body/renderers/formatted_field';
@@ -36,18 +36,28 @@ export const FieldValueCell = React.memo(
values,
}: FieldValueCellProps) => {
return (
-
+
{values != null &&
values.map((value, i) => {
if (fieldFromBrowserField == null) {
return (
-
- {value}
-
+
+
+ {value}
+
+
);
}
return (
-
+
{data.field === MESSAGE_FIELD_NAME ? (
) : (
@@ -63,10 +73,10 @@ export const FieldValueCell = React.memo(
linkValue={(getLinkValue && getLinkValue(data.field)) ?? linkValue}
/>
)}
-
+
);
})}
-
+
);
}
);
diff --git a/x-pack/plugins/security_solution/public/common/mock/mock_detail_item.ts b/x-pack/plugins/security_solution/public/common/mock/mock_detail_item.ts
index 3712d389edeb1..035bdbbceff88 100644
--- a/x-pack/plugins/security_solution/public/common/mock/mock_detail_item.ts
+++ b/x-pack/plugins/security_solution/public/common/mock/mock_detail_item.ts
@@ -139,3 +139,191 @@ export const generateMockDetailItemData = (): TimelineEventsDetailsItem[] => [
];
export const mockDetailItemData: TimelineEventsDetailsItem[] = generateMockDetailItemData();
+
+export const rawEventData = {
+ _index: '.ds-logs-endpoint.events.network-default-2021.09.28-000001',
+ _id: 'TUWyf3wBFCFU0qRJTauW',
+ _score: 1,
+ _source: {
+ agent: {
+ id: '2ac9e9b3-f6d5-4ce6-915d-8f1f8f413624',
+ type: 'endpoint',
+ version: '8.0.0-SNAPSHOT',
+ },
+ process: {
+ Ext: {
+ ancestry: [
+ 'MmFjOWU5YjMtZjZkNS00Y2U2LTkxNWQtOGYxZjhmNDEzNjI0LTIyMzY0LTEzMjc4NjA2NTAyLjA=',
+ 'MmFjOWU5YjMtZjZkNS00Y2U2LTkxNWQtOGYxZjhmNDEzNjI0LTEtMTMyNzA3Njg2OTIuMA==',
+ ],
+ },
+ name: 'filebeat',
+ pid: 22535,
+ entity_id: 'MmFjOWU5YjMtZjZkNS00Y2U2LTkxNWQtOGYxZjhmNDEzNjI0LTIyNTM1LTEzMjc4NjA2NTI4LjA=',
+ executable:
+ '/opt/Elastic/Agent/data/elastic-agent-058c40/install/filebeat-8.0.0-SNAPSHOT-linux-x86_64/filebeat',
+ },
+ destination: {
+ address: '127.0.0.1',
+ port: 9200,
+ ip: '127.0.0.1',
+ },
+ source: {
+ address: '127.0.0.1',
+ port: 54146,
+ ip: '127.0.0.1',
+ },
+ message: 'Endpoint network event',
+ network: {
+ transport: 'tcp',
+ type: 'ipv4',
+ },
+ '@timestamp': '2021-10-14T16:45:58.0310772Z',
+ ecs: {
+ version: '1.11.0',
+ },
+ data_stream: {
+ namespace: 'default',
+ type: 'logs',
+ dataset: 'endpoint.events.network',
+ },
+ elastic: {
+ agent: {
+ id: '12345',
+ },
+ },
+ host: {
+ hostname: 'test-linux-1',
+ os: {
+ Ext: {
+ variant: 'Debian',
+ },
+ kernel: '4.19.0-17-cloud-amd64 #1 SMP Debian 4.19.194-2 (2021-06-21)',
+ name: 'Linux',
+ family: 'debian',
+ type: 'linux',
+ version: '10',
+ platform: 'debian',
+ full: 'Debian 10',
+ },
+ ip: ['127.0.0.1', '::1', '10.1.2.3', '2001:0DB8:AC10:FE01::'],
+ name: 'test-linux-1',
+ id: '76ea303129f249aa7382338e4263eac1',
+ mac: ['aa:bb:cc:dd:ee:ff'],
+ architecture: 'x86_64',
+ },
+ event: {
+ agent_id_status: 'verified',
+ sequence: 44872,
+ ingested: '2021-10-14T16:46:04Z',
+ created: '2021-10-14T16:45:58.0310772Z',
+ kind: 'event',
+ module: 'endpoint',
+ action: 'connection_attempted',
+ id: 'MKPXftjGeHiQzUNj++++nn6R',
+ category: ['network'],
+ type: ['start'],
+ dataset: 'endpoint.events.network',
+ outcome: 'unknown',
+ },
+ user: {
+ Ext: {
+ real: {
+ name: 'root',
+ id: 0,
+ },
+ },
+ name: 'root',
+ id: 0,
+ },
+ group: {
+ Ext: {
+ real: {
+ name: 'root',
+ id: 0,
+ },
+ },
+ name: 'root',
+ id: 0,
+ },
+ },
+ fields: {
+ 'host.os.full.text': ['Debian 10'],
+ 'event.category': ['network'],
+ 'process.name.text': ['filebeat'],
+ 'host.os.name.text': ['Linux'],
+ 'host.os.full': ['Debian 10'],
+ 'host.hostname': ['test-linux-1'],
+ 'process.pid': [22535],
+ 'host.mac': ['42:01:0a:c8:00:32'],
+ 'elastic.agent.id': ['abcdefg-f6d5-4ce6-915d-8f1f8f413624'],
+ 'host.os.version': ['10'],
+ 'host.os.name': ['Linux'],
+ 'source.ip': ['127.0.0.1'],
+ 'destination.address': ['127.0.0.1'],
+ 'host.name': ['test-linux-1'],
+ 'event.agent_id_status': ['verified'],
+ 'event.kind': ['event'],
+ 'event.outcome': ['unknown'],
+ 'group.name': ['root'],
+ 'user.id': ['0'],
+ 'host.os.type': ['linux'],
+ 'process.Ext.ancestry': [
+ 'MmFjOWU5YjMtZjZkNS00Y2U2LTkxNWQtOGYxZjhmNDEzNjI0LTIyMzY0LTEzMjc4NjA2NTAyLjA=',
+ 'MmFjOWU5YjMtZjZkNS00Y2U2LTkxNWQtOGYxZjhmNDEzNjI0LTEtMTMyNzA3Njg2OTIuMA==',
+ ],
+ 'user.Ext.real.id': ['0'],
+ 'data_stream.type': ['logs'],
+ 'host.architecture': ['x86_64'],
+ 'process.name': ['filebeat'],
+ 'agent.id': ['2ac9e9b3-f6d5-4ce6-915d-8f1f8f413624'],
+ 'source.port': [54146],
+ 'ecs.version': ['1.11.0'],
+ 'event.created': ['2021-10-14T16:45:58.031Z'],
+ 'agent.version': ['8.0.0-SNAPSHOT'],
+ 'host.os.family': ['debian'],
+ 'destination.port': [9200],
+ 'group.id': ['0'],
+ 'user.name': ['root'],
+ 'source.address': ['127.0.0.1'],
+ 'process.entity_id': [
+ 'MmFjOWU5YjMtZjZkNS00Y2U2LTkxNWQtOGYxZjhmNDEzNjI0LTIyNTM1LTEzMjc4NjA2NTI4LjA=',
+ ],
+ 'host.ip': ['127.0.0.1', '::1', '10.1.2.3', '2001:0DB8:AC10:FE01::'],
+ 'process.executable.caseless': [
+ '/opt/elastic/agent/data/elastic-agent-058c40/install/filebeat-8.0.0-snapshot-linux-x86_64/filebeat',
+ ],
+ 'event.sequence': [44872],
+ 'agent.type': ['endpoint'],
+ 'process.executable.text': [
+ '/opt/Elastic/Agent/data/elastic-agent-058c40/install/filebeat-8.0.0-SNAPSHOT-linux-x86_64/filebeat',
+ ],
+ 'group.Ext.real.name': ['root'],
+ 'event.module': ['endpoint'],
+ 'host.os.kernel': ['4.19.0-17-cloud-amd64 #1 SMP Debian 4.19.194-2 (2021-06-21)'],
+ 'host.os.full.caseless': ['debian 10'],
+ 'host.id': ['76ea303129f249aa7382338e4263eac1'],
+ 'process.name.caseless': ['filebeat'],
+ 'network.type': ['ipv4'],
+ 'process.executable': [
+ '/opt/Elastic/Agent/data/elastic-agent-058c40/install/filebeat-8.0.0-SNAPSHOT-linux-x86_64/filebeat',
+ ],
+ 'user.Ext.real.name': ['root'],
+ 'data_stream.namespace': ['default'],
+ message: ['Endpoint network event'],
+ 'destination.ip': ['127.0.0.1'],
+ 'network.transport': ['tcp'],
+ 'host.os.Ext.variant': ['Debian'],
+ 'group.Ext.real.id': ['0'],
+ 'event.ingested': ['2021-10-14T16:46:04.000Z'],
+ 'event.action': ['connection_attempted'],
+ '@timestamp': ['2021-10-14T16:45:58.031Z'],
+ 'host.os.platform': ['debian'],
+ 'data_stream.dataset': ['endpoint.events.network'],
+ 'event.type': ['start'],
+ 'event.id': ['MKPXftjGeHiQzUNj++++nn6R'],
+ 'host.os.name.caseless': ['linux'],
+ 'event.dataset': ['endpoint.events.network'],
+ 'user.name.text': ['root'],
+ },
+};
diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx
index 17d43d80a5a9a..6a7f0602c3675 100644
--- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx
@@ -33,6 +33,7 @@ interface Props {
isDraggable?: boolean;
loading: boolean;
messageHeight?: number;
+ rawEventData: object | undefined;
timelineTabType: TimelineTabs | 'flyout';
timelineId: string;
hostRisk: HostRisk | null;
@@ -93,6 +94,7 @@ export const ExpandableEvent = React.memo(
loading,
detailsData,
hostRisk,
+ rawEventData,
}) => {
if (!event.eventId) {
return {i18n.EVENT_DETAILS_PLACEHOLDER};
@@ -111,6 +113,7 @@ export const ExpandableEvent = React.memo(
id={event.eventId}
isAlert={isAlert}
isDraggable={isDraggable}
+ rawEventData={rawEventData}
timelineId={timelineId}
timelineTabType={timelineTabType}
hostRisk={hostRisk}
diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx
index f8786e0706834..b9d7e0a8c024f 100644
--- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx
@@ -79,7 +79,7 @@ const EventDetailsPanelComponent: React.FC = ({
tabType,
timelineId,
}) => {
- const [loading, detailsData] = useTimelineEventsDetails({
+ const [loading, detailsData, rawEventData] = useTimelineEventsDetails({
docValueFields,
entityType,
indexName: expandedEvent.indexName ?? '',
@@ -195,6 +195,7 @@ const EventDetailsPanelComponent: React.FC = ({
isAlert={isAlert}
isDraggable={isDraggable}
loading={loading}
+ rawEventData={rawEventData}
timelineId={timelineId}
timelineTabType="flyout"
hostRisk={hostRisk}
@@ -228,6 +229,7 @@ const EventDetailsPanelComponent: React.FC = ({
isAlert={isAlert}
isDraggable={isDraggable}
loading={loading}
+ rawEventData={rawEventData}
timelineId={timelineId}
timelineTabType={tabType}
hostRisk={hostRisk}
diff --git a/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx
index e59eaeed4f2a6..f05966bd97870 100644
--- a/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx
@@ -42,7 +42,7 @@ export const useTimelineEventsDetails = ({
indexName,
eventId,
skip,
-}: UseTimelineEventsDetailsProps): [boolean, EventsArgs['detailsData']] => {
+}: UseTimelineEventsDetailsProps): [boolean, EventsArgs['detailsData'], object | undefined] => {
const { data } = useKibana().services;
const refetch = useRef(noop);
const abortCtrl = useRef(new AbortController());
@@ -55,6 +55,8 @@ export const useTimelineEventsDetails = ({
const [timelineDetailsResponse, setTimelineDetailsResponse] =
useState(null);
+ const [rawEventData, setRawEventData] = useState