From a59ce6119643452c4a22aca2328577a36c6223df Mon Sep 17 00:00:00 2001 From: Andrew Goldstein Date: Fri, 5 Feb 2021 14:13:57 -0700 Subject: [PATCH] [Security Solution] [Timeline] Endpoint row renderers (1st batch) (#89810) (#90499) ## [Security Solution] [Timeline] Endpoint row renderers (1st batch) This PR implements the 1st batch of Endpoint (`event.module: "endpoint"`) row renderers by updating and enhancing some of the existing "Endgame" (`event.module: "endgame"`) row renderers to use the latest [ECS fields](https://www.elastic.co/guide/en/ecs/current/ecs-field-reference.html). The following Endpoint events will be rendered via row renderers in Timeline: | event.dataset | event.action | |--------------------------|---------------------| | endpoint.events.file | creation | | endpoint.events.file | deletion | | endpoint.events.process | start | | endpoint.events.process | end | | endpoint.events.network | lookup_requested | | endpoint.events.network | lookup_result | | endpoint.events.network | connection_accepted | | endpoint.events.network | disconnect_received | | endpoint.events.security | log_on | | endpoint.events.security | log_off | ## File (FIM) Creation events Endpoint File (FIM) Creation events with the following `event.dataset` and `event.action` will be rendered in Timeline via row renderers: ``` event.dataset: endpoint.events.file and event.action: creation ``` ### Sample rendered File (FIM) Creation event ![endpoint_file_creation](https://user-images.githubusercontent.com/4459398/106036793-ff522f80-6092-11eb-9e3b-c24538129bea.png) Each field with `this formatting` is draggable (to pivot a search) in the row-rendered event: `SYSTEM` \ `NT AUTHORITY` @ `win2019-endpoint` created a file `WimProvider.dll` in `C:\Windows\TEMP\F590BACBAE94\WimProvider.dll` via `MsMpEng.exe` `(2424)` ### Fields in a File (FIM) Creation event `user.name` \ `user.domain` @ `host.name` created a file `file.name` in `file.path` via `process.name` `(process.pid)` ## File (FIM) Deletion events Endpoint File (FIM) Deletion events with the following `event.dataset` and `event.action` will be rendered in Timeline via row renderers: ``` event.dataset: endpoint.events.file and event.action: deletion ``` ### Sample rendered File (FIM) Deletion event ![endpoint_file_deletion](https://user-images.githubusercontent.com/4459398/106037520-088fcc00-6094-11eb-985d-ba8cead9fec9.png) `SYSTEM` \ `NT AUTHORITY` @ `windows-endpoint-1` deleted a file `AM_Delta_Patch_1.329.2793.0.exe` in `C:\Windows\SoftwareDistribution\Download\Install\AM_Delta_Patch_1.329.2793.0.exe` via `svchost.exe` `(1728)` ### Fields in a File (FIM) Deletion event `user.name` \ `user.domain` @ `host.name` deleted a file `file.name` in `file.path` via `process.name` `(process.pid)` ## Process Start events Endpoint Process Start events with the following `event.dataset` and `event.action` will be rendered in Timeline via row renderers: ``` event.dataset: endpoint.events.process and event.action: start ``` ### Sample rendered Process Start event ![creation-event](https://user-images.githubusercontent.com/4459398/106061579-c7f37b00-60b2-11eb-9bc4-224e671baa4a.png) `SYSTEM` \ `NT AUTHORITY` @ `win2019-endpoint` started process `conhost.exe` (`376`) `C:\Windows\system32\conhost.exe` `0xffffffff` `-ForceV1` via parent process `sshd.exe` (`6460`) `sha256 697334c236cce7d4c9e223146ee683a1219adced9729d4ae771fd6a1502a6b63` `sha1 e19da2c35ba1c38adf12d1a472c1fcf1f1a811a7` `md5 1b0e9b5fcb62de0787235ecca560b610` ### Fields in a Process Start event The following fields will be used to render a Process Start event: `user.name` \ `user.domain` @ `host.name` started process `process.name` (`process.pid`) `process.args` via parent process `process.parent.name` (`process.parent.pid`) `process.hash.sha256` `process.hash.sha1` `process.hash.md5` ## Process End events Endpoint Process End events with the following `event.dataset` and `event.action` will be rendered in Timeline via row renderers: ``` event.dataset: endpoint.events.process and event.action: end ``` ### Sample rendered Process End event ![endpoint_process_end](https://user-images.githubusercontent.com/4459398/106076527-f1b99b80-60cc-11eb-8ff8-2da78a1fcb8f.png) `SYSTEM` \ `NT AUTHORITY` @ `win2019-endpoint` terminated process `svchost.exe` (`10392`) `C:\Windows\System32\svchost.exe` `-k` `netsvcs` `-p` `-s` `NetSetupSvc` with exit code `0` via parent process `services.exe` `(568)` `7fd065bac18c5278777ae44908101cdfed72d26fa741367f0ad4d02020787ab6` `a1385ce20ad79f55df235effd9780c31442aa234` `8a0a29438052faed8a2532da50455756` ### Fields in a Process End event The following fields will be used to render a Process End event: `user.name` \ `user.domain` @ `host.name` terminated process `process.name` (`process.pid`) with exit code `process.exit_code` via parent process `process.parent.name` (`process.parent.pid`) `process.hash.sha256` `process.hash.sha1` `process.hash.md5` ## Network (DNS) Lookup Requested events Endpoint Network (DNS) Lookup Requested events with the following `event.dataset` and `event.action` will be rendered in Timeline via row renderers: ``` event.dataset: endpoint.events.network and event.action: lookup_requested ``` ### Runtime matching criteria All Network Lookup Requested events, including Endpoint and non-Endpoint DNS events matching the following criteria will be rendered: ``` dns.question.type: * and dns.question.name: * ``` ### Sample rendered Network Lookup Requested event ![network_lookup_requested](https://user-images.githubusercontent.com/4459398/106191208-cdf76380-6167-11eb-9be7-aaf78e4cfdd3.png) `SYSTEM` \ `NT AUTHORITY` @ `windows-endpoint-1` asked for `logging.googleapis.com` with question type `A` via `google_osconfig_agent.exe` `(4064)` `dns` ### Fields in a Network Lookup Requested event The following fields will be used to render a Network Lookup Request event: `user.name` \ `user.domain` @ `host.name` asked for `dns.question.name` with question type `dns.question.type` via `process.name` `(process.pid)` `network.protocol` ## Network Lookup Result events Endpoint Network (DNS) Lookup Result events with the following `event.dataset` and `event.action` will be rendered in Timeline via row renderers: ``` event.dataset: endpoint.events.network and event.action: lookup_result ``` ### Runtime matching criteria All Network Lookup Result events, including Endpoint and non-Endpoint DNS events matching the following criteria will be rendered: ``` dns.question.type: * and dns.question.name: * ``` ### Sample rendered Network Lookup Result event ![network_lookup_result](https://user-images.githubusercontent.com/4459398/106192595-a43f3c00-6169-11eb-95bc-4ebe331f1231.png) `SYSTEM` \ `NT AUTHORITY` @ `windows-endpoint-1` asked for `logging.googleapis.com` with question type `AAAA` via `GCEWindowsAgent.exe` `(684)` `dns` ### Fields in a Network Lookup Result event The following fields will be used to render a Network Lookup Result event: `user.name` \ `user.domain` @ `host.name` asked for `dns.question.name` with question type `dns.question.type` via `process.name` `(process.pid)` `network.protocol` ## Network Connection Accepted events Endpoint Network Connection Accepted events with the following `event.dataset` and `event.action` will be rendered in Timeline via row renderers: ``` event.dataset: endpoint.events.network and event.action: connection_accepted ```` ### Sample rendered Network Connection Accepted event ![network_connection_accepted](https://user-images.githubusercontent.com/4459398/106200497-4f54f300-6174-11eb-8879-06b7bfc88edf.png) Network Connection Accepted events, like the one in the screenshot above, are also rendered by the _Netflow_ row renderer, which displays information that includes the directionality of the connection, protocol, and source / destination details. `NETWORK SERVICE` \ `NT AUTHORITY` @ `windows-endpoint-1` accepted a connection via `svchost.exe` `(328)` with result `success` ### Fields in a Network Connection Accepted event `user.name` \ `user.domain` @ `host.name` accepted a connection via `process.name` `(process.pid)` with result `event.outcome` ## Network Disconnect Received events Endpoint Network Disconnect Received events with the following `event.dataset` and `event.action` will be rendered in Timeline via row renderers: ``` event.dataset: endpoint.events.network and event.action: disconnect_received ```` ### Sample rendered Network Disconnect Received event ![network_disconnect_received](https://user-images.githubusercontent.com/4459398/106205196-56cbca80-617b-11eb-83d3-26aa9670f114.png) Network Disconnect Received events, like the one in the screenshot above, are also rendered by the _Netflow_ row renderer, which displays information that includes the directionality of the connection, protocol, and source / destination details. `NETWORK SERVICE` \ `NT AUTHORITY` @ `windows-endpoint-1` disconnected via `svchost.exe` `(328)` ### Fields in a Network Disconnect Received event `user.name` \ `user.domain` @ `host.name` disconnected via `process.name` `(process.pid)` ## Security Log On events Endpoint Security Log On events with the following `event.dataset` and `event.action` will be rendered in Timeline via row renderers: ``` event.dataset: endpoint.events.security and event.action: log_on ``` ### `event.outcome: "success"` vs `event.outcome: "failure"` The row renderer for Security Log On events uses the `event.outcome` field to display different results for events matching: ``` event.dataset: endpoint.events.security and event.action: log_on and event.outcome: success ``` vs events matching: ``` event.dataset: endpoint.events.security and event.action: log_on and event.outcome: failure ``` ### Sample rendered Security Log On / `event.outcome: "success"` event ![security_log_on_success](https://user-images.githubusercontent.com/4459398/106210917-fcd00280-6184-11eb-9c1c-564cfb375539.png) `SYSTEM` \ `NT AUTHORITY` @ `win2019-endpoint` successfully logged in via `C:\Program Files\OpenSSH-Win64\sshd.exe` ### Fields in an Security Log On / `event.outcome: "success"` event `user.name` \ `user.domain` @ `host.name` successfully logged in via `process.name` (`process.pid`) ### Sample rendered Security Log On / `event.outcome: "failure"` event ![security_log_on_failure](https://user-images.githubusercontent.com/4459398/106211893-b2e81c00-6186-11eb-9c34-43227c15a1f0.png) `SYSTEM` \ `NT AUTHORITY` @ `win2019-endpoint` failed to log in via `C:\Program Files\OpenSSH-Win64\sshd.exe` ### Fields in an Security Log On / `event.outcome: "failure"` event `user.name` \ `user.domain` @ `host.name` failed to log in via `process.name` (`process.pid`) ## Security Log Off events Endpoint Security Log Off events with the following `event.dataset` and `event.action` will be rendered in Timeline via row renderers: ``` event.dataset: endpoint.events.security and event.action: log_off ``` ### Sample rendered Security Log Off event ![security_log_off](https://user-images.githubusercontent.com/4459398/106212499-0018bd80-6188-11eb-9e91-971f360ee87a.png) `SYSTEM` \ `NT AUTHORITY` @ `win2019-endpoint` logged off via `C:\Program Files\OpenSSH-Win64\sshd.exe` ### Fields in a Security Log Off event `user.name` \ `user.domain` @ `host.name` logged off via `process.name` (`process.pid`) --- .../common/ecs/process/index.ts | 6 + .../common/mock/mock_endgame_ecs_data.ts | 594 ++++++++++++++++++ .../process_draggable.test.tsx.snap | 43 +- .../endgame_security_event_details.tsx | 2 + ...dgame_security_event_details_line.test.tsx | 19 + .../endgame_security_event_details_line.tsx | 4 +- .../body/renderers/endgame/helpers.test.tsx | 112 +++- .../body/renderers/endgame/helpers.ts | 15 +- .../body/renderers/endgame/translations.ts | 14 + .../renderers/exit_code_draggable.test.tsx | 101 ++- .../body/renderers/exit_code_draggable.tsx | 34 +- .../timeline/body/renderers/helpers.tsx | 7 +- .../parent_process_draggable.test.tsx | 48 +- .../renderers/parent_process_draggable.tsx | 40 +- .../body/renderers/process_draggable.tsx | 85 +-- .../system/generic_file_details.test.tsx | 285 +++++++-- .../renderers/system/generic_file_details.tsx | 15 + .../system/generic_row_renderer.test.tsx | 264 ++++++++ .../renderers/system/generic_row_renderer.tsx | 65 +- .../timeline/factory/events/all/constants.ts | 3 + 20 files changed, 1590 insertions(+), 166 deletions(-) diff --git a/x-pack/plugins/security_solution/common/ecs/process/index.ts b/x-pack/plugins/security_solution/common/ecs/process/index.ts index cc4a961a5b528..3a8ccc309aecb 100644 --- a/x-pack/plugins/security_solution/common/ecs/process/index.ts +++ b/x-pack/plugins/security_solution/common/ecs/process/index.ts @@ -7,7 +7,9 @@ export interface ProcessEcs { entity_id?: string[]; + exit_code?: number[]; hash?: ProcessHashData; + parent?: ProcessParentData; pid?: number[]; name?: string[]; ppid?: number[]; @@ -24,6 +26,10 @@ export interface ProcessHashData { sha256?: string[]; } +export interface ProcessParentData { + name?: string[]; +} + export interface Thread { id?: number[]; start?: string[]; diff --git a/x-pack/plugins/security_solution/public/common/mock/mock_endgame_ecs_data.ts b/x-pack/plugins/security_solution/public/common/mock/mock_endgame_ecs_data.ts index 98bedbb08028b..1082b5f9474e5 100644 --- a/x-pack/plugins/security_solution/public/common/mock/mock_endgame_ecs_data.ts +++ b/x-pack/plugins/security_solution/public/common/mock/mock_endgame_ecs_data.ts @@ -58,6 +58,121 @@ export const mockEndgameDnsRequest: Ecs = { }, }; +export const mockEndpointNetworkLookupRequestedEvent: Ecs = { + host: { + os: { + full: ['Windows Server 2019 Datacenter 1809 (10.0.17763.1697)'], + name: ['Windows'], + version: ['1809 (10.0.17763.1697)'], + family: ['windows'], + kernel: ['1809 (10.0.17763.1697)'], + platform: ['windows'], + }, + mac: ['aa:bb:cc:dd:ee:ff'], + name: ['win2019-endpoint'], + architecture: ['x86_64'], + ip: ['10.1.2.3'], + id: ['d8ad572e-d224-4044-a57d-f5a84c0dfe5d'], + }, + event: { + category: ['network'], + kind: ['event'], + created: ['2021-01-25T16:44:40.788Z'], + module: ['endpoint'], + action: ['lookup_requested'], + type: ['protocol,info'], + id: ['LzzWB9jjGmCwGMvk++++6FZj'], + dataset: ['endpoint.events.network'], + }, + process: { + name: ['google_osconfig_agent.exe'], + pid: [3272], + entity_id: [ + 'MWQxNWNmOWUtM2RjNy01Yjk3LWY1ODYtNzQzZjdjMjUxOGIyLTMyNzItMTMyNTUwNzg4NjguNjUzODkxNTAw', + ], + executable: ['C:\\Program Files\\Google\\OSConfig\\google_osconfig_agent.exe'], + }, + dns: { + question: { + name: ['logging.googleapis.com'], + type: ['A'], + }, + }, + agent: { + type: ['endpoint'], + }, + user: { + name: ['SYSTEM'], + domain: ['NT AUTHORITY'], + }, + network: { + protocol: ['dns'], + }, + message: [ + 'DNS query is completed for the name logging.googleapis.com, type 1, query options 1073766400 with status 87 Results', + ], + timestamp: '2021-01-25T16:44:40.788Z', + _id: 'sUNzOncBPmkOXwyN9VbT', +}; + +export const mockEndpointNetworkLookupResultEvent: Ecs = { + host: { + os: { + full: ['Windows Server 2019 Datacenter 1809 (10.0.17763.1697)'], + name: ['Windows'], + version: ['1809 (10.0.17763.1697)'], + family: ['windows'], + kernel: ['1809 (10.0.17763.1697)'], + platform: ['windows'], + }, + mac: ['aa:bb:cc:dd:ee:ff'], + name: ['win2019-endpoint'], + architecture: ['x86_64'], + ip: ['10.1.2.3'], + id: ['d8ad572e-d224-4044-a57d-f5a84c0dfe5d'], + }, + event: { + category: ['network'], + kind: ['event'], + outcome: ['success'], + created: ['2021-01-25T16:44:40.789Z'], + module: ['endpoint'], + action: ['lookup_result'], + type: ['protocol,info'], + id: ['LzzWB9jjGmCwGMvk++++6FZq'], + dataset: ['endpoint.events.network'], + }, + process: { + name: ['google_osconfig_agent.exe'], + pid: [3272], + entity_id: [ + 'MWQxNWNmOWUtM2RjNy01Yjk3LWY1ODYtNzQzZjdjMjUxOGIyLTMyNzItMTMyNTUwNzg4NjguNjUzODkxNTAw', + ], + executable: ['C:\\Program Files\\Google\\OSConfig\\google_osconfig_agent.exe'], + }, + agent: { + type: ['endpoint'], + }, + dns: { + question: { + name: ['logging.googleapis.com'], + type: ['AAAA'], + }, + }, + user: { + name: ['SYSTEM'], + domain: ['NT AUTHORITY'], + }, + network: { + protocol: ['dns'], + }, + message: [ + 'DNS query is completed for the name logging.googleapis.com, type 28, query options 2251800887582720 with status 0 Results', + ], + timestamp: '2021-01-25T16:44:40.789Z', + _id: 'skNzOncBPmkOXwyN9VbT', +}; + export const mockEndgameFileCreateEvent: Ecs = { _id: '98jPcG0BOpWiDweSouzg', user: { @@ -91,6 +206,59 @@ export const mockEndgameFileCreateEvent: Ecs = { }, }; +export const mockEndpointFileCreationEvent: Ecs = { + file: { + path: ['C:\\Windows\\TEMP\\E38FD162-B6E6-4799-B52D-F590BACBAE94\\WimProvider.dll'], + extension: ['dll'], + name: ['WimProvider.dll'], + }, + host: { + os: { + full: ['Windows Server 2019 Datacenter 1809 (10.0.17763.1697)'], + name: ['Windows'], + version: ['1809 (10.0.17763.1697)'], + family: ['windows'], + kernel: ['1809 (10.0.17763.1697)'], + platform: ['windows'], + }, + mac: ['aa:bb:cc:dd:ee:ff'], + name: ['win2019-endpoint'], + architecture: ['x86_64'], + ip: ['10.9.8.7'], + id: ['d8ad572e-d224-4044-a57d-f5a84c0dfe5d'], + }, + event: { + category: ['file'], + kind: ['event'], + created: ['2021-01-25T16:21:56.832Z'], + module: ['endpoint'], + action: ['creation'], + type: ['creation'], + id: ['LzzWB9jjGmCwGMvk++++6FEM'], + dataset: ['endpoint.events.file'], + }, + process: { + name: ['MsMpEng.exe'], + pid: [2424], + entity_id: [ + 'MWQxNWNmOWUtM2RjNy01Yjk3LWY1ODYtNzQzZjdjMjUxOGIyLTI0MjQtMTMyNTUwNzg2OTAuNDQ1MzY0NzAw', + ], + executable: [ + 'C:\\ProgramData\\Microsoft\\Windows Defender\\Platform\\4.18.2011.6-0\\MsMpEng.exe', + ], + }, + agent: { + type: ['endpoint'], + }, + user: { + name: ['SYSTEM'], + domain: ['NT AUTHORITY'], + }, + message: ['Endpoint file event'], + timestamp: '2021-01-25T16:21:56.832Z', + _id: 'eSdbOncBLJMagDUQ3YFs', +}; + export const mockEndgameFileDeleteEvent: Ecs = { _id: 'OMjPcG0BOpWiDweSeuW9', user: { @@ -123,6 +291,58 @@ export const mockEndgameFileDeleteEvent: Ecs = { }, }; +export const mockEndpointFileDeletionEvent: Ecs = { + file: { + path: ['C:\\Windows\\SoftwareDistribution\\Download\\Install\\AM_Delta_Patch_1.329.2793.0.exe'], + extension: ['exe'], + name: ['AM_Delta_Patch_1.329.2793.0.exe'], + }, + host: { + os: { + full: ['Windows Server 2019 Datacenter 1809 (10.0.17763.1697)'], + name: ['Windows'], + version: ['1809 (10.0.17763.1697)'], + family: ['windows'], + kernel: ['1809 (10.0.17763.1697)'], + platform: ['windows'], + }, + mac: ['11:22:33:44:55:66'], + name: ['windows-endpoint-1'], + architecture: ['x86_64'], + ip: ['10.1.2.3'], + id: ['ce6fa3c3-fda1-4984-9bce-f6d602a5bd1a'], + }, + event: { + category: ['file'], + kind: ['event'], + created: ['2021-01-25T22:50:36.783Z'], + module: ['endpoint'], + action: ['deletion'], + type: ['deletion'], + id: ['Lzty2lsJxA05IUWg++++CBsc'], + dataset: ['endpoint.events.file'], + }, + process: { + name: ['svchost.exe'], + pid: [1728], + entity_id: [ + 'YjUwNDNiMTMtYTdjNi0xZGFlLTEyZWQtODQ1ZDlhNTRhZmQyLTE3MjgtMTMyNTQ5ODc2MjYuNjg3OTg0MDAw', + ], + executable: ['C:\\Windows\\System32\\svchost.exe'], + }, + user: { + id: ['S-1-5-18'], + name: ['SYSTEM'], + domain: ['NT AUTHORITY'], + }, + agent: { + type: ['endpoint'], + }, + message: ['Endpoint file event'], + timestamp: '2021-01-25T22:50:36.783Z', + _id: 'mnXHO3cBPmkOXwyNlyv_', +}; + export const mockEndgameIpv4ConnectionAcceptEvent: Ecs = { _id: 'LsjPcG0BOpWiDweSCNfu', user: { @@ -213,6 +433,74 @@ export const mockEndgameIpv6ConnectionAcceptEvent: Ecs = { }, }; +export const mockEndpointNetworkConnectionAcceptedEvent: Ecs = { + host: { + os: { + full: ['Windows Server 2019 Datacenter 1809 (10.0.17763.1697)'], + name: ['Windows'], + version: ['1809 (10.0.17763.1697)'], + family: ['windows'], + kernel: ['1809 (10.0.17763.1697)'], + platform: ['windows'], + }, + mac: ['aa:bb:cc:dd:ee:ff'], + name: ['windows-endpoint-1'], + architecture: ['x86_64'], + ip: ['10.1.2.3'], + id: ['ce6fa3c3-fda1-4984-9bce-f6d602a5bd1a'], + }, + event: { + category: ['network'], + kind: ['event'], + outcome: ['success'], + created: ['2021-01-25T16:44:45.048Z'], + module: ['endpoint'], + action: ['connection_accepted'], + type: ['start'], + id: ['Lzty2lsJxA05IUWg++++C1CY'], + dataset: ['endpoint.events.network'], + }, + process: { + name: ['svchost.exe'], + pid: [328], + entity_id: [ + 'YjUwNDNiMTMtYTdjNi0xZGFlLTEyZWQtODQ1ZDlhNTRhZmQyLTMyOC0xMzI1NDk4NzUwNS45OTYxMjUzMDA=', + ], + executable: ['C:\\Windows\\System32\\svchost.exe'], + }, + source: { + geo: { + region_name: ['North Carolina'], + region_iso_code: ['US-NC'], + city_name: ['Concord'], + country_iso_code: ['US'], + continent_name: ['North America'], + country_name: ['United States'], + }, + ip: ['10.1.2.3'], + port: [64557], + }, + destination: { + port: [3389], + ip: ['10.50.60.70'], + }, + user: { + id: ['S-1-5-20'], + name: ['NETWORK SERVICE'], + domain: ['NT AUTHORITY'], + }, + agent: { + type: ['endpoint'], + }, + network: { + direction: ['incoming'], + transport: ['tcp'], + }, + message: ['Endpoint network event'], + timestamp: '2021-01-25T16:44:45.048Z', + _id: 'tUN0OncBPmkOXwyNOGPV', +}; + export const mockEndgameIpv4DisconnectReceivedEvent: Ecs = { _id: 'hMjPcG0BOpWiDweSoOin', user: { @@ -309,6 +597,75 @@ export const mockEndgameIpv6DisconnectReceivedEvent: Ecs = { }, }; +export const mockEndpointDisconnectReceivedEvent: Ecs = { + host: { + os: { + full: ['Windows Server 2019 Datacenter 1809 (10.0.17763.1697)'], + name: ['Windows'], + version: ['1809 (10.0.17763.1697)'], + family: ['windows'], + kernel: ['1809 (10.0.17763.1697)'], + platform: ['windows'], + }, + mac: ['aa:bb:cc:dd:ee:ff'], + name: ['windows-endpoint-1'], + architecture: ['x86_64'], + ip: ['10.1.2.3'], + id: ['ce6fa3c3-fda1-4984-9bce-f6d602a5bd1a'], + }, + event: { + category: ['network'], + kind: ['event'], + created: ['2021-01-25T16:44:47.004Z'], + module: ['endpoint'], + action: ['disconnect_received'], + type: ['end'], + id: ['Lzty2lsJxA05IUWg++++C1Ch'], + dataset: ['endpoint.events.network'], + }, + process: { + name: ['svchost.exe'], + pid: [328], + entity_id: [ + 'YjUwNDNiMTMtYTdjNi0xZGFlLTEyZWQtODQ1ZDlhNTRhZmQyLTMyOC0xMzI1NDk4NzUwNS45OTYxMjUzMDA=', + ], + executable: ['C:\\Windows\\System32\\svchost.exe'], + }, + source: { + geo: { + region_name: ['North Carolina'], + region_iso_code: ['US-NC'], + city_name: ['Concord'], + country_iso_code: ['US'], + continent_name: ['North America'], + country_name: ['United States'], + }, + ip: ['10.20.30.40'], + port: [64557], + bytes: [1192], + }, + destination: { + bytes: [1615], + port: [3389], + ip: ['10.11.12.13'], + }, + user: { + id: ['S-1-5-20'], + name: ['NETWORK SERVICE'], + domain: ['NT AUTHORITY'], + }, + agent: { + type: ['endpoint'], + }, + network: { + direction: ['incoming'], + transport: ['tcp'], + }, + message: ['Endpoint network event'], + timestamp: '2021-01-25T16:44:47.004Z', + _id: 'uUN0OncBPmkOXwyNOGPV', +}; + export const mockEndgameUserLogon: Ecs = { _id: 'QsjPcG0BOpWiDweSeuRE', user: { @@ -357,6 +714,92 @@ export const mockEndgameUserLogon: Ecs = { }, }; +export const mockEndpointSecurityLogOnSuccessEvent: Ecs = { + host: { + os: { + full: ['Windows Server 2019 Datacenter 1809 (10.0.17763.1697)'], + name: ['Windows'], + version: ['1809 (10.0.17763.1697)'], + family: ['windows'], + kernel: ['1809 (10.0.17763.1697)'], + platform: ['windows'], + }, + mac: ['aa:bb:cc:dd:ee:ff'], + name: ['win2019-endpoint'], + architecture: ['x86_64'], + ip: ['10.1.2.3'], + id: ['d8ad572e-d224-4044-a57d-f5a84c0dfe5d'], + }, + event: { + category: ['authentication', 'session'], + kind: ['event'], + outcome: ['success'], + created: ['2021-01-25T16:24:51.761Z'], + module: ['endpoint'], + action: ['log_on'], + type: ['start'], + id: ['LzzWB9jjGmCwGMvk++++6FKC'], + dataset: ['endpoint.events.security'], + }, + process: { + name: ['C:\\Program Files\\OpenSSH-Win64\\sshd.exe'], + entity_id: [ + 'MWQxNWNmOWUtM2RjNy01Yjk3LWY1ODYtNzQzZjdjMjUxOGIyLTQzNDQtMTMyNTYwNjU0ODYuMzIwNDI3MDAw', + ], + executable: ['C:\\Program Files\\OpenSSH-Win64\\sshd.exe'], + pid: [90210], + }, + agent: { + type: ['endpoint'], + }, + user: { + name: ['SYSTEM'], + domain: ['NT AUTHORITY'], + }, + message: ['Endpoint security event'], + timestamp: '2021-01-25T16:24:51.761Z', + _id: 'eSlgOncBLJMagDUQ-yBL', +}; + +export const mockEndpointSecurityLogOnFailureEvent: Ecs = { + host: { + os: { + full: ['Windows Server 2019 Datacenter 1809 (10.0.17763.1637)'], + name: ['Windows'], + version: ['1809 (10.0.17763.1637)'], + kernel: ['1809 (10.0.17763.1637)'], + platform: ['windows'], + family: ['windows'], + }, + mac: ['aa:bb:cc:dd:ee:ff'], + ip: ['10.1.2.3'], + name: ['win2019-endpoint'], + id: ['d8ad572e-d224-4044-a57d-f5a84c0dfe5d'], + architecture: ['x86_64'], + }, + event: { + category: ['authentication', 'session'], + module: ['endpoint'], + kind: ['event'], + outcome: ['failure'], + action: ['log_on'], + created: ['2020-12-28T04:05:01.409Z'], + type: ['start'], + id: ['Ly1AjdVRChqy2iq3++++3jlX'], + dataset: ['endpoint.events.security'], + }, + process: { + name: ['C:\\Program Files\\OpenSSH-Win64\\sshd.exe'], + pid: [90210], + }, + agent: { + type: ['endpoint'], + }, + message: ['Endpoint security event'], + timestamp: '2020-12-28T04:05:01.409Z', + _id: 's8GIp3YBN9Y7_e914Upz', +}; + export const mockEndgameAdminLogon: Ecs = { _id: 'psjPcG0BOpWiDweSoelR', user: { @@ -488,6 +931,49 @@ export const mockEndgameUserLogoff: Ecs = { }, }; +export const mockEndpointSecurityLogOffEvent: Ecs = { + host: { + os: { + full: ['Windows Server 2019 Datacenter 1809 (10.0.17763.1697)'], + name: ['Windows'], + version: ['1809 (10.0.17763.1697)'], + family: ['windows'], + kernel: ['1809 (10.0.17763.1697)'], + platform: ['windows'], + }, + mac: ['aa:bb:cc:dd:ee:ff'], + name: ['win2019-endpoint'], + architecture: ['x86_64'], + ip: ['10.1.2.3'], + id: ['d8ad572e-d224-4044-a57d-f5a84c0dfe5d'], + }, + event: { + category: ['authentication,session'], + kind: ['event'], + outcome: ['success'], + created: ['2021-01-26T23:27:27.610Z'], + module: ['endpoint'], + action: ['log_off'], + type: ['end'], + id: ['LzzWB9jjGmCwGMvk++++6l0y'], + dataset: ['endpoint.events.security'], + }, + process: { + entity_id: [ + 'MWQxNWNmOWUtM2RjNy01Yjk3LWY1ODYtNzQzZjdjMjUxOGIyLTU4MC0xMzI1NTA3ODY2Ny45MTg5Njc1MDA=', + ], + executable: ['C:\\Windows\\System32\\lsass.exe'], + pid: [90210], + }, + user: { + name: ['SYSTEM'], + domain: ['NT AUTHORITY'], + }, + message: ['Endpoint security event'], + timestamp: '2021-01-26T23:27:27.610Z', + _id: 'ZesLQXcBPmkOXwyNdT1a', +}; + export const mockEndgameCreationEvent: Ecs = { _id: 'BcjPcG0BOpWiDweSou3g', user: { @@ -537,6 +1023,58 @@ export const mockEndgameCreationEvent: Ecs = { }, }; +export const mockEndpointProcessStartEvent: Ecs = { + process: { + hash: { + md5: ['1b0e9b5fcb62de0787235ecca560b610'], + sha256: ['697334c236cce7d4c9e223146ee683a1219adced9729d4ae771fd6a1502a6b63'], + sha1: ['e19da2c35ba1c38adf12d1a472c1fcf1f1a811a7'], + }, + name: ['conhost.exe'], + pid: [3636], + entity_id: [ + 'MWQxNWNmOWUtM2RjNy01Yjk3LWY1ODYtNzQzZjdjMjUxOGIyLTM2MzYtMTMyNTYwODU1OTguMTA3NTA3MDAw', + ], + executable: ['C:\\Windows\\System32\\conhost.exe'], + args: ['C:\\Windows\\system32\\conhost.exe,0xffffffff,-ForceV1'], + }, + host: { + os: { + full: ['Windows Server 2019 Datacenter 1809 (10.0.17763.1697)'], + name: ['Windows'], + version: ['1809 (10.0.17763.1697)'], + family: ['windows'], + kernel: ['1809 (10.0.17763.1697)'], + platform: ['windows'], + }, + mac: ['aa:bb:cc:dd:ee:ff'], + name: ['win2019-endpoint-1'], + architecture: ['x86_64'], + ip: ['10.1.2.3'], + id: ['d8ad572e-d224-4044-a57d-f5a84c0dfe5d'], + }, + event: { + category: ['process'], + kind: ['event'], + created: ['2021-01-25T21:59:58.107Z'], + module: ['endpoint'], + action: ['start'], + type: ['start'], + id: ['LzzWB9jjGmCwGMvk++++6Kw+'], + dataset: ['endpoint.events.process'], + }, + agent: { + type: ['endpoint'], + }, + user: { + name: ['SYSTEM'], + domain: ['NT AUTHORITY'], + }, + message: ['Endpoint process event'], + timestamp: '2021-01-25T21:59:58.107Z', + _id: 't5KSO3cB8l64wN2iQ8V9', +}; + export const mockEndgameTerminationEvent: Ecs = { _id: '2MjPcG0BOpWiDweSoutC', user: { @@ -578,3 +1116,59 @@ export const mockEndgameTerminationEvent: Ecs = { exit_code: [0], }, }; + +export const mockEndpointProcessEndEvent: Ecs = { + process: { + hash: { + md5: ['8a0a29438052faed8a2532da50455756'], + sha256: ['7fd065bac18c5278777ae44908101cdfed72d26fa741367f0ad4d02020787ab6'], + sha1: ['a1385ce20ad79f55df235effd9780c31442aa234'], + }, + name: ['svchost.exe'], + parent: { + name: ['services.exe'], + }, + pid: [10392], + entity_id: [ + 'MWQxNWNmOWUtM2RjNy01Yjk3LWY1ODYtNzQzZjdjMjUxOGIyLTEwMzkyLTEzMjU2MjY2OTkwLjcwMzgzMDgwMA==', + ], + executable: ['C:\\Windows\\System32\\svchost.exe'], + exit_code: [-1], + args: ['C:\\Windows\\System32\\svchost.exe,-k,netsvcs,-p,-s,NetSetupSvc'], + }, + host: { + os: { + full: ['Windows Server 2019 Datacenter 1809 (10.0.17763.1697)'], + name: ['Windows'], + version: ['1809 (10.0.17763.1697)'], + family: ['windows'], + kernel: ['1809 (10.0.17763.1697)'], + platform: ['windows'], + }, + mac: ['aa:bb:cc:dd:ee:ff'], + name: ['win2019-endpoint'], + architecture: ['x86_64'], + ip: ['10.1.2.3'], + id: ['d8ad572e-d224-4044-a57d-f5a84c0dfe5d'], + }, + event: { + category: ['process'], + kind: ['event'], + created: ['2021-01-28T00:24:05.929Z'], + module: ['endpoint'], + action: ['end'], + type: ['end'], + id: ['LzzWB9jjGmCwGMvk++++77mE'], + dataset: ['endpoint.events.process'], + }, + agent: { + type: ['endpoint'], + }, + user: { + name: ['SYSTEM'], + domain: ['NT AUTHORITY'], + }, + message: ['Endpoint process event'], + timestamp: '2021-01-28T00:24:05.929Z', + _id: 'quloRncBX5UUcOOYo2ZS', +}; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/__snapshots__/process_draggable.test.tsx.snap b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/__snapshots__/process_draggable.test.tsx.snap index 494a2b2b7732b..84aea591337ee 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/__snapshots__/process_draggable.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/__snapshots__/process_draggable.test.tsx.snap @@ -1,20 +1,31 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`ProcessDraggable rendering it renders against shallow snapshot 1`] = ` -
- - -
+ + + + + + + + `; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details.tsx index 819c77343fc14..515db45e9fcd4 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details.tsx @@ -42,6 +42,7 @@ export const EndgameSecurityEventDetails = React.memo(({ data, contextId, const endgameTargetUserName: string | null | undefined = get('endgame.target_user_name[0]', data); const eventAction: string | null | undefined = get('event.action[0]', data); const eventCode: string | null | undefined = get('event.code[0]', data); + const eventOutcome: string | null | undefined = get('event.outcome[0]', data); const hostName: string | null | undefined = get('host.name[0]', data); const id = data._id; const processExecutable: string | null | undefined = get('process.executable[0]', data); @@ -64,6 +65,7 @@ export const EndgameSecurityEventDetails = React.memo(({ data, contextId, endgameTargetUserName={endgameTargetUserName} eventAction={eventAction} eventCode={eventCode} + eventOutcome={eventOutcome} hostName={hostName} id={id} processExecutable={processExecutable} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.test.tsx index a502180edfcf1..5d08898789821 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.test.tsx @@ -39,6 +39,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="admin_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -69,6 +70,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="explicit_user_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -99,6 +101,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="explicit_user_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -129,6 +132,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="explicit_user_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -159,6 +163,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="explicit_user_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -189,6 +194,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="explicit_user_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -219,6 +225,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="explicit_user_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -249,6 +256,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="explicit_user_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -279,6 +287,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName={undefined} eventAction="explicit_user_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -309,6 +318,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction={undefined} eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -339,6 +349,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="explicit_user_logon" eventCode={undefined} + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -369,6 +380,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="explicit_user_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName={undefined} id="1" processExecutable="[processExecutable]" @@ -399,6 +411,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="explicit_user_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable={undefined} @@ -429,6 +442,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="explicit_user_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -459,6 +473,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="explicit_user_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -489,6 +504,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="admin_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -519,6 +535,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="admin_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -549,6 +566,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="admin_logon" eventCode="[eventCode]" + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" @@ -579,6 +597,7 @@ describe('EndgameSecurityEventDetailsLine', () => { endgameTargetUserName="[endgameTargetUserName]" eventAction="admin_logon" eventCode={undefined} + eventOutcome={undefined} hostName="[hostName]" id="1" processExecutable="[processExecutable]" diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.tsx index 9d3e74435852a..aba6f7346271d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.tsx @@ -35,6 +35,7 @@ interface Props { endgameTargetUserName: string | null | undefined; eventAction: string | null | undefined; eventCode: string | null | undefined; + eventOutcome: string | null | undefined; hostName: string | null | undefined; id: string; processExecutable: string | null | undefined; @@ -57,6 +58,7 @@ export const EndgameSecurityEventDetailsLine = React.memo( endgameTargetUserName, eventAction, eventCode, + eventOutcome, hostName, id, processExecutable, @@ -67,7 +69,7 @@ export const EndgameSecurityEventDetailsLine = React.memo( winlogEventId, }) => { const domain = getTargetUserAndTargetDomain(eventAction) ? endgameTargetDomainName : userDomain; - const eventDetails = getEventDetails(eventAction); + const eventDetails = getEventDetails({ eventAction, eventOutcome }); const hostNameSeparator = getHostNameSeparator(eventAction); const user = getTargetUserAndTargetDomain(eventAction) ? endgameTargetUserName : userName; const userDomainField = getUserDomainField(eventAction); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/helpers.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/helpers.test.tsx index a8955ccf22fec..5efc1e0b15673 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/helpers.test.tsx @@ -182,28 +182,116 @@ describe('helpers', () => { }); describe('#getEventDetails', () => { - test('it returns successfully logged in when eventAction is undefined', () => { - expect(getEventDetails(undefined)).toEqual('successfully logged in'); + test('it returns an empty string when eventAction is "explicit_user_logon"', () => { + expect( + getEventDetails({ eventAction: 'explicit_user_logon', eventOutcome: undefined }) + ).toEqual(''); }); - test('it returns successfully logged in when eventAction is null', () => { - expect(getEventDetails(null)).toEqual('successfully logged in'); + test('it returns logged off when eventAction is "log_off" and eventOutcome is null', () => { + expect(getEventDetails({ eventAction: 'log_off', eventOutcome: null })).toEqual('logged off'); }); - test('it returns successfully logged in when eventAction is an empty string', () => { - expect(getEventDetails('')).toEqual('successfully logged in'); + test('it returns logged off when eventAction is "log_off" and eventOutcome is undefined', () => { + expect(getEventDetails({ eventAction: 'log_off', eventOutcome: undefined })).toEqual( + 'logged off' + ); }); - test('it returns successfully logged in when eventAction is a random value', () => { - expect(getEventDetails('a random value')).toEqual('successfully logged in'); + test('it returns failed to log off when eventAction is "log_off" and eventOutcome is failure', () => { + expect(getEventDetails({ eventAction: 'log_off', eventOutcome: 'failure' })).toEqual( + 'failed to log off' + ); }); - test('it returns an empty string when eventAction is "explicit_user_logon"', () => { - expect(getEventDetails('explicit_user_logon')).toEqual(''); + test('it returns failed to log off when eventAction is "log_off" and eventOutcome is fAiLuRe', () => { + expect(getEventDetails({ eventAction: 'log_off', eventOutcome: 'fAiLuRe' })).toEqual( + 'failed to log off' + ); + }); + + test('it returns logged off when eventAction is "log_off" and eventOutcome is anything_else', () => { + expect(getEventDetails({ eventAction: 'log_off', eventOutcome: 'anything_else' })).toEqual( + 'logged off' + ); + }); + + test('it returns logged off when eventAction is "user_logoff" and eventOutcome is null', () => { + expect(getEventDetails({ eventAction: 'user_logoff', eventOutcome: null })).toEqual( + 'logged off' + ); + }); + + test('it returns logged off when eventAction is "user_logoff" and eventOutcome is undefined', () => { + expect(getEventDetails({ eventAction: 'user_logoff', eventOutcome: undefined })).toEqual( + 'logged off' + ); + }); + + test('it returns failed to log off when eventAction is "user_logoff" and eventOutcome is failure', () => { + expect(getEventDetails({ eventAction: 'user_logoff', eventOutcome: 'failure' })).toEqual( + 'failed to log off' + ); + }); + + test('it returns failed to log off when eventAction is "user_logoff" and eventOutcome is fAiLuRe', () => { + expect(getEventDetails({ eventAction: 'user_logoff', eventOutcome: 'fAiLuRe' })).toEqual( + 'failed to log off' + ); + }); + + test('it returns logged off when eventAction is "user_logoff" and eventOutcome is anything_else', () => { + expect( + getEventDetails({ eventAction: 'user_logoff', eventOutcome: 'anything_else' }) + ).toEqual('logged off'); + }); + + test('it returns successfully logged in when eventAction is null and eventOutcome is undefined', () => { + expect(getEventDetails({ eventAction: null, eventOutcome: undefined })).toEqual( + 'successfully logged in' + ); + }); + + test('it returns successfully logged in when eventAction is null and eventOutcome is null', () => { + expect(getEventDetails({ eventAction: null, eventOutcome: null })).toEqual( + 'successfully logged in' + ); + }); + + test('it returns successfully logged in when eventAction is undefined and eventOutcome is null', () => { + expect(getEventDetails({ eventAction: undefined, eventOutcome: null })).toEqual( + 'successfully logged in' + ); + }); + + test('it returns successfully logged in when eventAction is undefined and eventOutcome is undefined', () => { + expect(getEventDetails({ eventAction: undefined, eventOutcome: undefined })).toEqual( + 'successfully logged in' + ); + }); + + test('it returns successfully logged in when eventAction is anything_else and eventOutcome is undefined', () => { + expect(getEventDetails({ eventAction: 'anything_else', eventOutcome: undefined })).toEqual( + 'successfully logged in' + ); + }); + + test('it returns successfully logged in when eventAction is anything_else and eventOutcome is null', () => { + expect(getEventDetails({ eventAction: 'anything_else', eventOutcome: null })).toEqual( + 'successfully logged in' + ); + }); + + test('it returns failed to log in when eventAction is anything_else and eventOutcome is failure', () => { + expect(getEventDetails({ eventAction: 'anything_else', eventOutcome: 'failure' })).toEqual( + 'failed to log in' + ); }); - test('it returns logged off when eventAction is "user_logoff"', () => { - expect(getEventDetails('user_logoff')).toEqual('logged off'); + test('it returns failed to log in when eventAction is anything_else and eventOutcome is fAiLuRe', () => { + expect(getEventDetails({ eventAction: 'anything_else', eventOutcome: 'fAiLuRe' })).toEqual( + 'failed to log in' + ); }); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/helpers.ts b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/helpers.ts index 86785c3986270..87c0ed2782f9d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/helpers.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/helpers.ts @@ -50,13 +50,22 @@ export const getUserDomainField = (eventAction: string | null | undefined): stri export const getUserNameField = (eventAction: string | null | undefined): string => getTargetUserAndTargetDomain(eventAction) ? 'endgame.target_user_name' : 'user.name'; -export const getEventDetails = (eventAction: string | null | undefined): string => { +export const getEventDetails = ({ + eventAction, + eventOutcome, +}: { + eventAction: string | null | undefined; + eventOutcome: string | null | undefined; +}): string => { switch (eventAction) { case 'explicit_user_logon': return ''; // no details + case 'log_off': // fall through case 'user_logoff': - return i18n.LOGGED_OFF; + return eventOutcome?.toLowerCase() === 'failure' ? i18n.FAILED_TO_LOG_OFF : i18n.LOGGED_OFF; default: - return i18n.SUCCESSFULLY_LOGGED_IN; + return eventOutcome?.toLowerCase() === 'failure' + ? i18n.FAILED_TO_LOG_IN + : i18n.SUCCESSFULLY_LOGGED_IN; } }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/translations.ts b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/translations.ts index e7dfefb2b570c..859fc8ead332a 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/translations.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/translations.ts @@ -21,6 +21,20 @@ export const AS_REQUESTED_BY_SUBJECT = i18n.translate( } ); +export const FAILED_TO_LOG_IN = i18n.translate( + 'xpack.securitySolution.timeline.body.renderers.endpoint.failedToLogInDescription', + { + defaultMessage: 'failed to log in', + } +); + +export const FAILED_TO_LOG_OFF = i18n.translate( + 'xpack.securitySolution.timeline.body.renderers.endpoint.failedToLogOffDescription', + { + defaultMessage: 'failed to log off', + } +); + export const LOGGED_OFF = i18n.translate( 'xpack.securitySolution.timeline.body.renderers.endgame.loggedOffDescription', { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.test.tsx index 2d502f1195995..a6f15a9f79f4e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.test.tsx @@ -25,22 +25,29 @@ jest.mock('@elastic/eui', () => { describe('ExitCodeDraggable', () => { const mount = useMountAppended(); - test('it renders the expected text and exit code, when both text and an endgameExitCode are provided', () => { + test('it renders the expected text and exit codes, when text, processExitCode, and an endgameExitCode are provided', () => { const wrapper = mount( - + ); - expect(wrapper.text()).toEqual('with exit code0'); + expect(wrapper.text()).toEqual('with exit code-10'); }); - test('it returns an empty string when text is provided, but endgameExitCode is undefined', () => { + test('it returns an empty string when text is provided, but processExitCode and endgameExitCode are undefined', () => { const wrapper = mount( @@ -48,13 +55,14 @@ describe('ExitCodeDraggable', () => { expect(wrapper.text()).toEqual(''); }); - test('it returns an empty string when text is provided, but endgameExitCode is null', () => { + test('it returns an empty string when text is provided, but processExitCode and endgameExitCode are null', () => { const wrapper = mount( @@ -65,36 +73,105 @@ describe('ExitCodeDraggable', () => { test('it returns an empty string when text is provided, but endgameExitCode is an empty string', () => { const wrapper = mount( - + ); expect(wrapper.text()).toEqual(''); }); - test('it renders just the exit code when text is undefined', () => { + test('it renders just the endgameExitCode code when text is undefined', () => { const wrapper = mount( - + ); expect(wrapper.text()).toEqual('1'); }); - test('it renders just the exit code when text is null', () => { + test('it renders just the processExitCode code when text is undefined', () => { const wrapper = mount( - + + + ); + expect(wrapper.text()).toEqual('-1'); + }); + + test('it renders just the endgameExitCode code when text is null', () => { + const wrapper = mount( + + ); expect(wrapper.text()).toEqual('1'); }); - test('it renders just the exit code when text is an empty string', () => { + test('it renders just the processExitCode code when text is null', () => { const wrapper = mount( - + + + ); + expect(wrapper.text()).toEqual('-1'); + }); + + test('it renders just the endgameExitCode code when text is an empty string', () => { + const wrapper = mount( + + ); expect(wrapper.text()).toEqual('1'); }); + + test('it renders just the processExitCode code when text is an empty string', () => { + const wrapper = mount( + + + + ); + expect(wrapper.text()).toEqual('-1'); + }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.tsx index 7d680aeb2ea76..7ac9fe290893f 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.tsx @@ -15,12 +15,13 @@ interface Props { contextId: string; endgameExitCode: string | null | undefined; eventId: string; + processExitCode: number | null | undefined; text: string | null | undefined; } export const ExitCodeDraggable = React.memo( - ({ contextId, endgameExitCode, eventId, text }) => { - if (isNillEmptyOrNotFinite(endgameExitCode)) { + ({ contextId, endgameExitCode, eventId, processExitCode, text }) => { + if (isNillEmptyOrNotFinite(processExitCode) && isNillEmptyOrNotFinite(endgameExitCode)) { return null; } @@ -32,14 +33,27 @@ export const ExitCodeDraggable = React.memo( )} - - - + {!isNillEmptyOrNotFinite(processExitCode) && ( + + + + )} + + {!isNillEmptyOrNotFinite(endgameExitCode) && ( + + + + )} ); } diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/helpers.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/helpers.tsx index 1dfff526dcce6..ea84dc19908f0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/helpers.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/helpers.tsx @@ -51,14 +51,15 @@ export const isFileEvent = ({ eventCategory: string | null | undefined; eventDataset: string | null | undefined; }) => - (eventCategory != null && eventCategory.toLowerCase() === 'file') || - (eventDataset != null && eventDataset.toLowerCase() === 'file'); + eventCategory?.toLowerCase() === 'file' || + eventDataset?.toLowerCase() === 'file' || + eventDataset?.toLowerCase() === 'endpoint.events.file'; export const isProcessStoppedOrTerminationEvent = ( eventAction: string | null | undefined ): boolean => ['process_stopped', 'termination_event'].includes(`${eventAction}`.toLowerCase()); export const showVia = (eventAction: string | null | undefined): boolean => - ['file_create_event', 'created', 'file_delete_event', 'deleted'].includes( + ['file_create_event', 'created', 'creation', 'file_delete_event', 'deleted', 'deletion'].includes( `${eventAction}`.toLowerCase() ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.test.tsx index 19fd5eee0e230..2402be88dea18 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.test.tsx @@ -25,28 +25,34 @@ jest.mock('@elastic/eui', () => { describe('ParentProcessDraggable', () => { const mount = useMountAppended(); - test('displays the text, endgameParentProcessName, and processPpid when they are all provided', () => { + test('displays the text, endgameParentProcessName, processParentName, processParentPid, and processPpid when they are all provided', () => { const wrapper = mount( ); - expect(wrapper.text()).toEqual('via parent process[endgameParentProcessName](456)'); + expect(wrapper.text()).toEqual( + 'via parent process[processParentName][endgameParentProcessName](789)(456)' + ); }); - test('displays nothing when the text is provided, but endgameParentProcessName and processPpid are both undefined', () => { + test('displays nothing when the text is provided, but endgameParentProcessName and processParentName are both undefined', () => { const wrapper = mount( @@ -55,63 +61,71 @@ describe('ParentProcessDraggable', () => { expect(wrapper.text()).toEqual(''); }); - test('displays the text and processPpid when endgameParentProcessName is undefined', () => { + test('displays the text and endgameParentProcessName when processPpid is undefined', () => { const wrapper = mount( ); - expect(wrapper.text()).toEqual('via parent process(456)'); + expect(wrapper.text()).toEqual('via parent process[endgameParentProcessName]'); }); - test('displays the processPpid when both endgameParentProcessName and text are undefined', () => { + test('displays the text and processParentName when processParentPid is undefined', () => { const wrapper = mount( ); - expect(wrapper.text()).toEqual('(456)'); + expect(wrapper.text()).toEqual('via parent process[processParentName]'); }); - test('displays the text and endgameParentProcessName when processPpid is undefined', () => { + test('displays the endgameParentProcessName when both processPpid and text are undefined', () => { const wrapper = mount( ); - expect(wrapper.text()).toEqual('via parent process[endgameParentProcessName]'); + expect(wrapper.text()).toEqual('[endgameParentProcessName]'); }); - test('displays the endgameParentProcessName when both processPpid and text are undefined', () => { + test('displays the processParentName when both processParentPid and text are undefined', () => { const wrapper = mount( ); - expect(wrapper.text()).toEqual('[endgameParentProcessName]'); + expect(wrapper.text()).toEqual('[processParentName]'); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.tsx index 816b2c8ddae78..f0a63404feeb7 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.tsx @@ -15,13 +15,26 @@ interface Props { contextId: string; endgameParentProcessName: string | null | undefined; eventId: string; + processParentPid: number | null | undefined; + processParentName: string | null | undefined; processPpid: number | undefined | null; text: string | null | undefined; } export const ParentProcessDraggable = React.memo( - ({ contextId, endgameParentProcessName, eventId, processPpid, text }) => { - if (isNillEmptyOrNotFinite(endgameParentProcessName) && isNillEmptyOrNotFinite(processPpid)) { + ({ + contextId, + endgameParentProcessName, + eventId, + processParentName, + processParentPid, + processPpid, + text, + }) => { + if ( + isNillEmptyOrNotFinite(processParentName) && + isNillEmptyOrNotFinite(endgameParentProcessName) + ) { return null; } @@ -37,6 +50,17 @@ export const ParentProcessDraggable = React.memo( )} + {!isNillEmptyOrNotFinite(processParentName) && ( + + + + )} + {!isNillEmptyOrNotFinite(endgameParentProcessName) && ( ( )} + {!isNillEmptyOrNotFinite(processParentPid) && ( + + + + )} + {!isNillEmptyOrNotFinite(processPpid) && ( ( } return ( -
+ {!isNillEmptyOrNotFinite(processName) ? ( - + + + ) : !isNillEmptyOrNotFinite(processExecutable) ? ( - + + + ) : !isNillEmptyOrNotFinite(endgameProcessName) ? ( - + + + ) : null} {!isNillEmptyOrNotFinite(processPid) ? ( - + + + ) : !isNillEmptyOrNotFinite(endgamePid) ? ( - + + + ) : null} -
+ ); } ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.test.tsx index 536de70a712a8..a3932fde44c1d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.test.tsx @@ -116,10 +116,13 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageExecutable=123]" + processExecutable="[processExecutable=123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1="[processHashSha1-123]" processHashSha256="[processHashSha256-123]" + processParentName="[processParentName-123]" + processParentPid={789} processPid={123} processPpid={456} processName="[processName-123]" @@ -135,7 +138,7 @@ describe('SystemGenericFileDetails', () => {
); expect(wrapper.text()).toEqual( - '[username-123]\\[userDomain-123]@[hostname-123]in[working-directory-123][generic-text-123][fileName-123]in[filePath-123][processName-123](123)[arg-1][arg-2][arg-3][some-title-123]with exit code[endgameExitCode-123]via parent process[endgameParentProcessName-123](456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' + '[username-123]\\[userDomain-123]@[hostname-123]in[working-directory-123][generic-text-123][fileName-123]in[filePath-123][processName-123](123)[arg-1][arg-2][arg-3][some-title-123]with exit code-1[endgameExitCode-123]via parent process[processParentName-123][endgameParentProcessName-123](789)(456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' ); }); @@ -162,9 +165,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={null} packageVersion={null} processExecutable={null} + processExitCode={null} processHashMd5={null} processHashSha1={null} processHashSha256={null} + processParentName={null} + processParentPid={null} processPid={null} processPpid={null} processName={null} @@ -207,9 +213,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={null} packageVersion={null} processExecutable={null} + processExitCode={null} processHashMd5={null} processHashSha1={null} processHashSha256={null} + processParentName={null} + processParentPid={null} processPid={null} processPpid={null} processName={null} @@ -252,9 +261,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={null} packageVersion={null} processExecutable={null} + processExitCode={null} processHashMd5={null} processHashSha1={null} processHashSha256={null} + processParentName={null} + processParentPid={null} processPid={null} processPpid={null} processName={null} @@ -297,9 +309,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={null} packageVersion={null} processExecutable={null} + processExitCode={null} processHashMd5={null} processHashSha1={null} processHashSha256={null} + processParentName={null} + processParentPid={null} processPid={null} processPpid={null} processName={null} @@ -344,9 +359,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={null} packageVersion={null} processExecutable={null} + processExitCode={null} processHashMd5={null} processHashSha1={null} processHashSha256={null} + processParentName={null} + processParentPid={null} processPid={null} processPpid={null} processName={null} @@ -391,9 +409,12 @@ describe('SystemGenericFileDetails', () => { packageSummary="[packageSummary-123]" packageVersion={null} processExecutable={null} + processExitCode={null} processHashMd5={null} processHashSha1={null} processHashSha256={null} + processParentName={null} + processParentPid={null} processPid={null} processPpid={null} processName={null} @@ -438,9 +459,12 @@ describe('SystemGenericFileDetails', () => { packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" processExecutable={null} + processExitCode={null} processHashMd5={null} processHashSha1={null} processHashSha256={null} + processParentName={null} + processParentPid={null} processPid={null} processPpid={null} processName={null} @@ -462,7 +486,7 @@ describe('SystemGenericFileDetails', () => { ); }); - test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable', () => { + test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processExitCode', () => { const wrapper = mount(
@@ -484,10 +508,13 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageVersion-123]" + processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5={null} processHashSha1={null} processHashSha256={null} + processParentName={null} + processParentPid={null} processPid={null} processPpid={null} processName={null} @@ -505,11 +532,11 @@ describe('SystemGenericFileDetails', () => { ); expect(wrapper.text()).toEqual( - '[hostname-123][packageVersion-123]with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][message-123]' + '[hostname-123][processExecutable-123]with exit code-1with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][message-123]' ); }); - test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processHashMd5', () => { + test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5', () => { const wrapper = mount(
@@ -531,10 +558,13 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageVersion-123]" + processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1={null} processHashSha256={null} + processParentName={null} + processParentPid={null} processPid={null} processPpid={null} processName={null} @@ -552,11 +582,11 @@ describe('SystemGenericFileDetails', () => { ); expect(wrapper.text()).toEqual( - '[hostname-123][packageVersion-123]with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][processHashMd5-123][message-123]' + '[hostname-123][processExecutable-123]with exit code-1with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][processHashMd5-123][message-123]' ); }); - test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processHashMd5, processHashSha1', () => { + test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1', () => { const wrapper = mount(
@@ -578,10 +608,63 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageVersion-123]" + processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1="[processHashSha1-123]" processHashSha256={null} + processParentName={null} + processParentPid={null} + processPid={null} + processPpid={null} + processName={null} + showMessage={true} + sshMethod={null} + sshSignature={null} + text={null} + userDomain={null} + userName={null} + workingDirectory={null} + processTitle={null} + args={null} + /> +
+
+ ); + expect(wrapper.text()).toEqual( + '[hostname-123][processExecutable-123]with exit code-1with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha1-123][processHashMd5-123][message-123]' + ); + }); + + test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1, processHashSha256', () => { + const wrapper = mount( + +
+ { ); expect(wrapper.text()).toEqual( - '[hostname-123][packageVersion-123]with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha1-123][processHashMd5-123][message-123]' + '[hostname-123][processExecutable-123]with exit code-1with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' ); }); - test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processHashMd5, processHashSha1, processHashSha256', () => { + test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1, processHashSha256, processParentName', () => { const wrapper = mount(
@@ -625,10 +708,13 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageVersion-123]" + processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1="[processHashSha1-123]" processHashSha256="[processHashSha256-123]" + processParentName="[processParentName-123]" + processParentPid={null} processPid={null} processPpid={null} processName={null} @@ -646,11 +732,11 @@ describe('SystemGenericFileDetails', () => { ); expect(wrapper.text()).toEqual( - '[hostname-123][packageVersion-123]with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' + '[hostname-123][processExecutable-123]with exit code-1via parent process[processParentName-123]with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' ); }); - test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processHashMd5, processHashSha1, processHashSha256, processPid', () => { + test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1, processHashSha256, processParentName, processParentPid', () => { const wrapper = mount(
@@ -673,9 +759,62 @@ describe('SystemGenericFileDetails', () => { packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1="[processHashSha1-123]" processHashSha256="[processHashSha256-123]" + processParentName="[processParentName-123]" + processParentPid={789} + processPid={null} + processPpid={null} + processName={null} + showMessage={true} + sshMethod={null} + sshSignature={null} + text={null} + userDomain={null} + userName={null} + workingDirectory={null} + processTitle={null} + args={null} + /> +
+
+ ); + expect(wrapper.text()).toEqual( + '[hostname-123][processExecutable-123]with exit code-1via parent process[processParentName-123](789)with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' + ); + }); + + test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1, processHashSha256, processParentName, processParentPid, processPid', () => { + const wrapper = mount( + +
+ { ); expect(wrapper.text()).toEqual( - '[hostname-123][processExecutable-123](123)with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' + '[hostname-123][processExecutable-123](123)with exit code-1via parent process[processParentName-123](789)with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' ); }); - test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processHashMd5, processHashSha1, processHashSha256, processPid, processPpid, processName', () => { + test('it can return the host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1, processHashSha256, processParentName, processParentPid, processPid, processPpid, processName', () => { const wrapper = mount(
@@ -719,10 +858,13 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageVersion-123]" + processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1="[processHashSha1-123]" processHashSha256="[processHashSha256-123]" + processParentName="[processParentName-123]" + processParentPid={789} processPid={123} processPpid={456} processName="[processName-123]" @@ -740,11 +882,11 @@ describe('SystemGenericFileDetails', () => { ); expect(wrapper.text()).toEqual( - '[hostname-123][processName-123](123)via parent process(456)with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' + '[hostname-123][processName-123](123)with exit code-1via parent process[processParentName-123](789)(456)with result[outcome-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' ); }); - test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processHashMd5, processHashSha1, processHashSha256, processPid, processPpid, processName, sshMethod', () => { + test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1, processHashSha256, processParentName, processParentPid, processPid, processPpid, processName, sshMethod', () => { const wrapper = mount(
@@ -766,10 +908,13 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageVersion-123]" + processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1="[processHashSha1-123]" processHashSha256="[processHashSha256-123]" + processParentName="[processParentName-123]" + processParentPid={789} processPid={123} processPpid={456} processName="[processName-123]" @@ -787,11 +932,11 @@ describe('SystemGenericFileDetails', () => { ); expect(wrapper.text()).toEqual( - '[hostname-123][processName-123](123)with exit code[endgameExitCode-123]via parent process[endgameParentProcessName-123](456)with result[outcome-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' + '[hostname-123][processName-123](123)with exit code-1[endgameExitCode-123]via parent process[processParentName-123][endgameParentProcessName-123](789)(456)with result[outcome-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' ); }); - test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processHashMd5, processHashSha1, processHashSha256, processPid, processPpid, processName, sshMethod, sshSignature', () => { + test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1, processHashSha256, processParentName, processParentPid, processPid, processPpid, processName, sshMethod, sshSignature', () => { const wrapper = mount(
@@ -813,10 +958,13 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageVersion-123]" + processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1="[processHashSha1-123]" processHashSha256="[processHashSha256-123]" + processParentName="[processParentName-123]" + processParentPid={789} processPid={123} processPpid={456} processName="[processName-123]" @@ -834,11 +982,11 @@ describe('SystemGenericFileDetails', () => { ); expect(wrapper.text()).toEqual( - '[hostname-123][processName-123](123)with exit code[endgameExitCode-123]via parent process[endgameParentProcessName-123](456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' + '[hostname-123][processName-123](123)with exit code-1[endgameExitCode-123]via parent process[processParentName-123][endgameParentProcessName-123](789)(456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' ); }); - test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processHashMd5, processHashSha1, processHashSha256, processPid, processPpid, processName, sshMethod, sshSignature, text', () => { + test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1, processHashSha256, processParentName, processParentPid, processPid, processPpid, processName, sshMethod, sshSignature, text', () => { const wrapper = mount(
@@ -860,10 +1008,13 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageVersion-123]" + processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1="[processHashSha1-123]" processHashSha256="[processHashSha256-123]" + processParentName="[processParentName-123]" + processParentPid={789} processPid={123} processPpid={456} processName="[processName-123]" @@ -881,11 +1032,11 @@ describe('SystemGenericFileDetails', () => { ); expect(wrapper.text()).toEqual( - '[hostname-123][text-123][processName-123](123)with exit code[endgameExitCode-123]via parent process[endgameParentProcessName-123](456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' + '[hostname-123][text-123][processName-123](123)with exit code-1[endgameExitCode-123]via parent process[processParentName-123][endgameParentProcessName-123](789)(456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' ); }); - test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processHashMd5, processHashSha1, processHashSha256, processPid, processPpid, processName, sshMethod, sshSignature, text, userDomain', () => { + test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1, processHashSha256, processParentName, processParentPid, processPid, processPpid, processName, sshMethod, sshSignature, text, userDomain', () => { const wrapper = mount(
@@ -907,10 +1058,13 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageVersion-123]" + processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1="[processHashSha1-123]" processHashSha256="[processHashSha256-123]" + processParentName="[processParentName-123]" + processParentPid={789} processPid={123} processPpid={456} processName="[processName-123]" @@ -928,11 +1082,11 @@ describe('SystemGenericFileDetails', () => { ); expect(wrapper.text()).toEqual( - '\\[userDomain-123][hostname-123][text-123][processName-123](123)with exit code[endgameExitCode-123]via parent process[endgameParentProcessName-123](456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' + '\\[userDomain-123][hostname-123][text-123][processName-123](123)with exit code-1[endgameExitCode-123]via parent process[processParentName-123][endgameParentProcessName-123](789)(456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' ); }); - test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processHashMd5, processHashSha1, processHashSha256, processPid, processPpid, processName, sshMethod, sshSignature, text, userDomain, username', () => { + test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1, processHashSha256, processParentName, processParentPid, processPid, processPpid, processName, sshMethod, sshSignature, text, userDomain, username', () => { const wrapper = mount(
@@ -954,10 +1108,13 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageVersion-123]" + processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1="[processHashSha1-123]" processHashSha256="[processHashSha256-123]" + processParentName="[processParentName-123]" + processParentPid={789} processPid={123} processPpid={456} processName="[processName-123]" @@ -975,11 +1132,11 @@ describe('SystemGenericFileDetails', () => { ); expect(wrapper.text()).toEqual( - '[username-123]\\[userDomain-123]@[hostname-123][text-123][processName-123](123)with exit code[endgameExitCode-123]via parent process[endgameParentProcessName-123](456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' + '[username-123]\\[userDomain-123]@[hostname-123][text-123][processName-123](123)with exit code-1[endgameExitCode-123]via parent process[processParentName-123][endgameParentProcessName-123](789)(456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' ); }); - test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processHashMd5, processHashSha1, processHashSha256, processPid, processPpid, processName, sshMethod, sshSignature, text, userDomain, username, working-directory', () => { + test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1, processHashSha256, processParentName, processParentPid, processPid, processPpid, processName, sshMethod, sshSignature, text, userDomain, username, working-directory', () => { const wrapper = mount(
@@ -1001,10 +1158,13 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageVersion-123]" + processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1="[processHashSha1-123]" processHashSha256="[processHashSha256-123]" + processParentName="[processParentName-123]" + processParentPid={789} processPid={123} processPpid={456} processName="[processName-123]" @@ -1022,11 +1182,11 @@ describe('SystemGenericFileDetails', () => { ); expect(wrapper.text()).toEqual( - '[username-123]\\[userDomain-123]@[hostname-123]in[working-directory-123][text-123][processName-123](123)with exit code[endgameExitCode-123]via parent process[endgameParentProcessName-123](456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' + '[username-123]\\[userDomain-123]@[hostname-123]in[working-directory-123][text-123][processName-123](123)with exit code-1[endgameExitCode-123]via parent process[processParentName-123][endgameParentProcessName-123](789)(456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' ); }); - test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processHashMd5, processHashSha1, processHashSha256, processPid, processPpid, processName, sshMethod, sshSignature, text, userDomain, username, working-directory, process-title', () => { + test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1, processHashSha256, processParentName, processParentPid, processPid, processPpid, processName, sshMethod, sshSignature, text, userDomain, username, working-directory, process-title', () => { const wrapper = mount(
@@ -1048,10 +1208,13 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageVersion-123]" + processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1="[processHashSha1-123]" processHashSha256="[processHashSha256-123]" + processParentName="[processParentName-123]" + processParentPid={789} processPid={123} processPpid={456} processName="[processName-123]" @@ -1069,11 +1232,11 @@ describe('SystemGenericFileDetails', () => { ); expect(wrapper.text()).toEqual( - '[username-123]\\[userDomain-123]@[hostname-123]in[working-directory-123][text-123][processName-123](123)[process-title-123]with exit code[endgameExitCode-123]via parent process[endgameParentProcessName-123](456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' + '[username-123]\\[userDomain-123]@[hostname-123]in[working-directory-123][text-123][processName-123](123)[process-title-123]with exit code-1[endgameExitCode-123]via parent process[processParentName-123][endgameParentProcessName-123](789)(456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' ); }); - test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, packageExecutable, processHashMd5, processHashSha1, processHashSha256, processPid, processPpid, processName, sshMethod, sshSignature, text, userDomain, username, working-directory, process-title, args', () => { + test('it can return the endgameExitCode, endgameParentProcessName, eventAction, host, message, outcome, packageName, pacakgeSummary, packageVersion, processExecutable, processExitCode, processHashMd5, processHashSha1, processHashSha256, processParentName, processParentPid, processPid, processPpid, processName, sshMethod, sshSignature, text, userDomain, username, working-directory, process-title, args', () => { const wrapper = mount(
@@ -1095,10 +1258,13 @@ describe('SystemGenericFileDetails', () => { packageName="[packageName-123]" packageSummary="[packageSummary-123]" packageVersion="[packageVersion-123]" - processExecutable="[packageVersion-123]" + processExecutable="[processExecutable-123]" + processExitCode={-1} processHashMd5="[processHashMd5-123]" processHashSha1="[processHashSha1-123]" processHashSha256="[processHashSha256-123]" + processParentName="[processParentName-123]" + processParentPid={789} processPid={123} processPpid={456} processName="[processName-123]" @@ -1116,7 +1282,7 @@ describe('SystemGenericFileDetails', () => { ); expect(wrapper.text()).toEqual( - '[username-123]\\[userDomain-123]@[hostname-123]in[working-directory-123][text-123][processName-123](123)[arg-1][arg-2][arg-3][process-title-123]with exit code[endgameExitCode-123]via parent process[endgameParentProcessName-123](456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' + '[username-123]\\[userDomain-123]@[hostname-123]in[working-directory-123][text-123][processName-123](123)[arg-1][arg-2][arg-3][process-title-123]with exit code-1[endgameExitCode-123]via parent process[processParentName-123][endgameParentProcessName-123](789)(456)with result[outcome-123][sshSignature-123][sshMethod-123][packageName-123][packageVersion-123][packageSummary-123][processHashSha256-123][processHashSha1-123][processHashMd5-123][message-123]' ); }); @@ -1143,9 +1309,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={undefined} packageVersion={undefined} processExecutable={undefined} + processExitCode={undefined} processHashMd5={undefined} processHashSha1={undefined} processHashSha256={undefined} + processParentName={undefined} + processParentPid={undefined} processPid={undefined} processPpid={undefined} processName={undefined} @@ -1188,9 +1357,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={undefined} packageVersion={undefined} processExecutable={undefined} + processExitCode={undefined} processHashMd5={undefined} processHashSha1={undefined} processHashSha256={undefined} + processParentName={undefined} + processParentPid={undefined} processPid={undefined} processPpid={undefined} processName={undefined} @@ -1235,9 +1407,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={undefined} packageVersion={undefined} processExecutable={undefined} + processExitCode={undefined} processHashMd5={undefined} processHashSha1={undefined} processHashSha256={undefined} + processParentName={undefined} + processParentPid={undefined} processPid={undefined} processPpid={undefined} processName={undefined} @@ -1284,9 +1459,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={undefined} packageVersion={undefined} processExecutable={undefined} + processExitCode={undefined} processHashMd5={undefined} processHashSha1={undefined} processHashSha256={undefined} + processParentName={undefined} + processParentPid={undefined} processPid={undefined} processPpid={undefined} processName={undefined} @@ -1332,9 +1510,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={undefined} packageVersion={undefined} processExecutable={undefined} + processExitCode={undefined} processHashMd5={undefined} processHashSha1={undefined} processHashSha256={undefined} + processParentName={undefined} + processParentPid={undefined} processPid={undefined} processPpid={456} processName={undefined} @@ -1382,9 +1563,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={undefined} packageVersion={undefined} processExecutable={undefined} + processExitCode={undefined} processHashMd5={undefined} processHashSha1={undefined} processHashSha256={undefined} + processParentName={undefined} + processParentPid={undefined} processPid={undefined} processPpid={456} processName={undefined} @@ -1430,9 +1614,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={undefined} packageVersion={undefined} processExecutable={undefined} + processExitCode={undefined} processHashMd5={undefined} processHashSha1={undefined} processHashSha256={undefined} + processParentName={undefined} + processParentPid={undefined} processPid={undefined} processPpid={456} processName={undefined} @@ -1476,9 +1663,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={undefined} packageVersion={undefined} processExecutable={undefined} + processExitCode={undefined} processHashMd5={undefined} processHashSha1={undefined} processHashSha256={undefined} + processParentName={undefined} + processParentPid={undefined} processPid={undefined} processPpid={undefined} processName={undefined} @@ -1522,9 +1712,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={undefined} packageVersion={undefined} processExecutable={undefined} + processExitCode={undefined} processHashMd5={undefined} processHashSha1={undefined} processHashSha256={undefined} + processParentName={undefined} + processParentPid={undefined} processPid={undefined} processPpid={undefined} processName={undefined} @@ -1568,9 +1761,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={undefined} packageVersion={undefined} processExecutable={undefined} + processExitCode={undefined} processHashMd5={undefined} processHashSha1={undefined} processHashSha256={undefined} + processParentName={undefined} + processParentPid={undefined} processPid={undefined} processPpid={undefined} processName={undefined} @@ -1614,9 +1810,12 @@ describe('SystemGenericFileDetails', () => { packageSummary={undefined} packageVersion={undefined} processExecutable={undefined} + processExitCode={undefined} processHashMd5={undefined} processHashSha1={undefined} processHashSha256={undefined} + processParentName={undefined} + processParentPid={undefined} processPid={123} processPpid={undefined} processName="[processName]" diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.tsx index e0e0743fb3043..4026613ff7d0a 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.tsx @@ -48,6 +48,9 @@ interface Props { packageSummary: string | null | undefined; packageVersion: string | null | undefined; processName: string | null | undefined; + processParentName: string | null | undefined; + processParentPid: number | null | undefined; + processExitCode: number | null | undefined; processPid: number | null | undefined; processPpid: number | null | undefined; processExecutable: string | null | undefined; @@ -82,6 +85,9 @@ export const SystemGenericFileLine = React.memo( message, outcome, packageName, + processParentName, + processParentPid, + processExitCode, packageSummary, packageVersion, processExecutable, @@ -142,6 +148,7 @@ export const SystemGenericFileLine = React.memo( contextId={contextId} endgameExitCode={endgameExitCode} eventId={id} + processExitCode={processExitCode} text={i18n.WITH_EXIT_CODE} /> {!isProcessStoppedOrTerminationEvent(eventAction) && ( @@ -149,6 +156,8 @@ export const SystemGenericFileLine = React.memo( contextId={contextId} endgameParentProcessName={endgameParentProcessName} eventId={id} + processParentName={processParentName} + processParentPid={processParentPid} processPpid={processPpid} text={i18n.VIA_PARENT_PROCESS} /> @@ -239,6 +248,9 @@ export const SystemGenericFileDetails = React.memo( const packageName: string | null | undefined = get('system.audit.package.name[0]', data); const packageSummary: string | null | undefined = get('system.audit.package.summary[0]', data); const packageVersion: string | null | undefined = get('system.audit.package.version[0]', data); + const processExitCode: number | null | undefined = get('process.exit_code[0]', data); + const processParentName: string | null | undefined = get('process.parent.name[0]', data); + const processParentPid: number | null | undefined = get('process.parent.pid[0]', data); const processHashMd5: string | null | undefined = get('process.hash.md5[0]', data); const processHashSha1: string | null | undefined = get('process.hash.sha1[0]', data); const processHashSha256: string | null | undefined = get('process.hash.sha256[0]', data); @@ -271,6 +283,9 @@ export const SystemGenericFileDetails = React.memo( userDomain={userDomain} userName={userName} message={message} + processExitCode={processExitCode} + processParentName={processParentName} + processParentPid={processParentPid} processTitle={processTitle} workingDirectory={workingDirectory} args={args} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.test.tsx index 23c7770d1f25b..4de9bcbdd9c18 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.test.tsx @@ -36,6 +36,17 @@ import { mockEndgameTerminationEvent, mockEndgameUserLogoff, mockEndgameUserLogon, + mockEndpointDisconnectReceivedEvent, + mockEndpointFileCreationEvent, + mockEndpointFileDeletionEvent, + mockEndpointNetworkConnectionAcceptedEvent, + mockEndpointNetworkLookupRequestedEvent, + mockEndpointNetworkLookupResultEvent, + mockEndpointProcessStartEvent, + mockEndpointProcessEndEvent, + mockEndpointSecurityLogOnSuccessEvent, + mockEndpointSecurityLogOnFailureEvent, + mockEndpointSecurityLogOffEvent, } from '../../../../../../common/mock/mock_endgame_ecs_data'; import { useMountAppended } from '../../../../../../common/utils/use_mount_appended'; import { RowRenderer } from '../row_renderer'; @@ -187,6 +198,31 @@ describe('GenericRowRenderer', () => { }); describe('#createEndgameProcessRowRenderer', () => { + test('it renders an endpoint process start event', () => { + const actionName = 'start'; + const text = i18n.PROCESS_STARTED; + + const endpointProcessStartRowRenderer = createEndgameProcessRowRenderer({ + actionName, + text, + }); + + const wrapper = mount( + + {endpointProcessStartRowRenderer.isInstance(mockEndpointProcessStartEvent) && + endpointProcessStartRowRenderer.renderRow({ + browserFields: mockBrowserFields, + data: mockEndpointProcessStartEvent, + timelineId: 'test', + })} + + ); + + expect(wrapper.text()).toEqual( + 'SYSTEM\\NT AUTHORITY@win2019-endpoint-1started processconhost.exe(3636)C:\\Windows\\system32\\conhost.exe,0xffffffff,-ForceV1697334c236cce7d4c9e223146ee683a1219adced9729d4ae771fd6a1502a6b63e19da2c35ba1c38adf12d1a472c1fcf1f1a811a71b0e9b5fcb62de0787235ecca560b610' + ); + }); + test('it renders an endgame process creation_event', () => { const actionName = 'creation_event'; const text = i18n.PROCESS_STARTED; @@ -215,6 +251,31 @@ describe('GenericRowRenderer', () => { ); }); + test('it renders an endpoint process end event', () => { + const actionName = 'end'; + const text = i18n.TERMINATED_PROCESS; + + const endpointProcessEndRowRenderer = createEndgameProcessRowRenderer({ + actionName, + text, + }); + + const wrapper = mount( + + {endpointProcessEndRowRenderer.isInstance(mockEndpointProcessEndEvent) && + endpointProcessEndRowRenderer.renderRow({ + browserFields: mockBrowserFields, + data: mockEndpointProcessEndEvent, + timelineId: 'test', + })} + + ); + + expect(wrapper.text()).toEqual( + 'SYSTEM\\NT AUTHORITY@win2019-endpointterminated processsvchost.exe(10392)C:\\Windows\\System32\\svchost.exe,-k,netsvcs,-p,-s,NetSetupSvcwith exit code-1via parent processservices.exe7fd065bac18c5278777ae44908101cdfed72d26fa741367f0ad4d02020787ab6a1385ce20ad79f55df235effd9780c31442aa2348a0a29438052faed8a2532da50455756' + ); + }); + test('it renders an endgame process termination_event', () => { const actionName = 'termination_event'; const text = i18n.TERMINATED_PROCESS; @@ -331,6 +392,31 @@ describe('GenericRowRenderer', () => { }); describe('#createFimRowRenderer', () => { + test('it renders an endpoint file creation event', () => { + const actionName = 'creation'; + const text = i18n.CREATED_FILE; + + const endpointFileCreationRowRenderer = createFimRowRenderer({ + actionName, + text, + }); + + const wrapper = mount( + + {endpointFileCreationRowRenderer.isInstance(mockEndpointFileCreationEvent) && + endpointFileCreationRowRenderer.renderRow({ + browserFields: mockBrowserFields, + data: mockEndpointFileCreationEvent, + timelineId: 'test', + })} + + ); + + expect(wrapper.text()).toEqual( + 'SYSTEM\\NT AUTHORITY@win2019-endpointcreated a fileWimProvider.dllinC:\\Windows\\TEMP\\E38FD162-B6E6-4799-B52D-F590BACBAE94\\WimProvider.dllviaMsMpEng.exe(2424)' + ); + }); + test('it renders an endgame file_create_event', () => { const actionName = 'file_create_event'; const text = i18n.CREATED_FILE; @@ -359,6 +445,31 @@ describe('GenericRowRenderer', () => { ); }); + test('it renders an endpoint file deletion event', () => { + const actionName = 'deletion'; + const text = i18n.DELETED_FILE; + + const endpointFileDeletionRowRenderer = createFimRowRenderer({ + actionName, + text, + }); + + const wrapper = mount( + + {endpointFileDeletionRowRenderer.isInstance(mockEndpointFileDeletionEvent) && + endpointFileDeletionRowRenderer.renderRow({ + browserFields: mockBrowserFields, + data: mockEndpointFileDeletionEvent, + timelineId: 'test', + })} + + ); + + expect(wrapper.text()).toEqual( + 'SYSTEM\\NT AUTHORITY@windows-endpoint-1deleted a fileAM_Delta_Patch_1.329.2793.0.exeinC:\\Windows\\SoftwareDistribution\\Download\\Install\\AM_Delta_Patch_1.329.2793.0.exeviasvchost.exe(1728)' + ); + }); + test('it renders an endgame file_delete_event', () => { const actionName = 'file_delete_event'; const text = i18n.DELETED_FILE; @@ -529,6 +640,33 @@ describe('GenericRowRenderer', () => { }); describe('#createSocketRowRenderer', () => { + test('it renders an Endpoint network connection_accepted event', () => { + const actionName = 'connection_accepted'; + const text = i18n.ACCEPTED_A_CONNECTION_VIA; + + const endpointConnectionAcceptedRowRenderer = createSocketRowRenderer({ + actionName, + text, + }); + + const wrapper = mount( + + {endpointConnectionAcceptedRowRenderer.isInstance( + mockEndpointNetworkConnectionAcceptedEvent + ) && + endpointConnectionAcceptedRowRenderer.renderRow({ + browserFields: mockBrowserFields, + data: mockEndpointNetworkConnectionAcceptedEvent, + timelineId: 'test', + })} + + ); + + expect(removeExternalLinkText(wrapper.text())).toEqual( + 'NETWORK SERVICE\\NT AUTHORITY@windows-endpoint-1accepted a connection viasvchost.exe(328)with resultsuccessEndpoint network eventincomingtcpSource10.1.2.3:64557North AmericaUnited States🇺🇸USNorth CarolinaConcordDestination10.50.60.70:3389' + ); + }); + test('it renders an Endgame ipv4_connection_accept_event', () => { const actionName = 'ipv4_connection_accept_event'; const text = i18n.ACCEPTED_A_CONNECTION_VIA; @@ -585,6 +723,31 @@ describe('GenericRowRenderer', () => { ); }); + test('it renders an endpoint network disconnect_received event', () => { + const actionName = 'disconnect_received'; + const text = i18n.DISCONNECTED_VIA; + + const endpointDisconnectReceivedRowRenderer = createSocketRowRenderer({ + actionName, + text, + }); + + const wrapper = mount( + + {endpointDisconnectReceivedRowRenderer.isInstance(mockEndpointDisconnectReceivedEvent) && + endpointDisconnectReceivedRowRenderer.renderRow({ + browserFields: mockBrowserFields, + data: mockEndpointDisconnectReceivedEvent, + timelineId: 'test', + })} + + ); + + expect(removeExternalLinkText(wrapper.text())).toEqual( + 'NETWORK SERVICE\\NT AUTHORITY@windows-endpoint-1disconnected viasvchost.exe(328)Endpoint network eventincomingtcpSource10.20.30.40:64557North AmericaUnited States🇺🇸USNorth CarolinaConcord(42.47%)1.2KB(57.53%)1.6KBDestination10.11.12.13:3389' + ); + }); + test('it renders an Endgame ipv4_disconnect_received_event', () => { const actionName = 'ipv4_disconnect_received_event'; const text = i18n.DISCONNECTED_VIA; @@ -725,6 +888,48 @@ describe('GenericRowRenderer', () => { }); describe('#createSecurityEventRowRenderer', () => { + test('it renders an endpoint security log_on event with event.outcome: success', () => { + const actionName = 'log_on'; + + const securityLogOnRowRenderer = createSecurityEventRowRenderer({ actionName }); + + const wrapper = mount( + + {securityLogOnRowRenderer.isInstance(mockEndpointSecurityLogOnSuccessEvent) && + securityLogOnRowRenderer.renderRow({ + browserFields: mockBrowserFields, + data: mockEndpointSecurityLogOnSuccessEvent, + timelineId: 'test', + })} + + ); + + expect(wrapper.text()).toEqual( + 'SYSTEM\\NT AUTHORITY@win2019-endpointsuccessfully logged inviaC:\\Program Files\\OpenSSH-Win64\\sshd.exe(90210)' + ); + }); + + test('it renders an endpoint security log_on event with event.outcome: failure', () => { + const actionName = 'log_on'; + + const securityLogOnRowRenderer = createSecurityEventRowRenderer({ actionName }); + + const wrapper = mount( + + {securityLogOnRowRenderer.isInstance(mockEndpointSecurityLogOnFailureEvent) && + securityLogOnRowRenderer.renderRow({ + browserFields: mockBrowserFields, + data: mockEndpointSecurityLogOnFailureEvent, + timelineId: 'test', + })} + + ); + + expect(wrapper.text()).toEqual( + 'win2019-endpointfailed to log inviaC:\\Program Files\\OpenSSH-Win64\\sshd.exe(90210)' + ); + }); + test('it renders an Endgame user_logon event', () => { const actionName = 'user_logon'; const userLogonEvent = { @@ -797,6 +1002,27 @@ describe('GenericRowRenderer', () => { ); }); + test('it renders an endpoint security log_off event', () => { + const actionName = 'log_off'; + + const securityLogOffRowRenderer = createSecurityEventRowRenderer({ actionName }); + + const wrapper = mount( + + {securityLogOffRowRenderer.isInstance(mockEndpointSecurityLogOffEvent) && + securityLogOffRowRenderer.renderRow({ + browserFields: mockBrowserFields, + data: mockEndpointSecurityLogOffEvent, + timelineId: 'test', + })} + + ); + + expect(wrapper.text()).toEqual( + 'SYSTEM\\NT AUTHORITY@win2019-endpointlogged offviaC:\\Windows\\System32\\lsass.exe(90210)' + ); + }); + test('it renders an Endgame user_logoff event', () => { const actionName = 'user_logoff'; const userLogoffEvent = { @@ -845,6 +1071,44 @@ describe('GenericRowRenderer', () => { }); describe('#createDnsRowRenderer', () => { + test('it renders an endpoint network lookup_requested event', () => { + const dnsRowRenderer = createDnsRowRenderer(); + + const wrapper = mount( + + {dnsRowRenderer.isInstance(mockEndpointNetworkLookupRequestedEvent) && + dnsRowRenderer.renderRow({ + browserFields: mockBrowserFields, + data: mockEndpointNetworkLookupRequestedEvent, + timelineId: 'test', + })} + + ); + + expect(wrapper.text()).toEqual( + 'SYSTEM\\NT AUTHORITY@win2019-endpointasked forlogging.googleapis.comwith question typeAviagoogle_osconfig_agent.exe(3272)dns' + ); + }); + + test('it renders an endpoint network lookup_result event', () => { + const dnsRowRenderer = createDnsRowRenderer(); + + const wrapper = mount( + + {dnsRowRenderer.isInstance(mockEndpointNetworkLookupResultEvent) && + dnsRowRenderer.renderRow({ + browserFields: mockBrowserFields, + data: mockEndpointNetworkLookupResultEvent, + timelineId: 'test', + })} + + ); + + expect(wrapper.text()).toEqual( + 'SYSTEM\\NT AUTHORITY@win2019-endpointasked forlogging.googleapis.comwith question typeAAAAviagoogle_osconfig_agent.exe(3272)dns' + ); + }); + test('it renders an Endgame DNS request_event', () => { const requestEvent = { ...mockEndgameDnsRequest, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.tsx index 431fc2592c8d1..69a6317ebcd11 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.tsx @@ -63,11 +63,11 @@ export const createEndgameProcessRowRenderer = ({ isInstance: (ecs) => { const action: string | null | undefined = get('event.action[0]', ecs); const category: string | null | undefined = get('event.category[0]', ecs); + const dataset: string | null | undefined = get('event.dataset[0]', ecs); return ( - category != null && - category.toLowerCase() === 'process' && - action != null && - action.toLowerCase() === actionName + (category?.toLowerCase() === 'process' || + dataset?.toLowerCase() === 'endpoint.events.process') && + action?.toLowerCase() === actionName ); }, renderRow: ({ browserFields, data, timelineId }) => ( @@ -98,8 +98,7 @@ export const createFimRowRenderer = ({ const dataset: string | null | undefined = get('event.dataset[0]', ecs); return ( isFileEvent({ eventCategory: category, eventDataset: dataset }) && - action != null && - action.toLowerCase() === actionName + action?.toLowerCase() === actionName ); }, renderRow: ({ browserFields, data, timelineId }) => ( @@ -181,11 +180,11 @@ export const createSecurityEventRowRenderer = ({ isInstance: (ecs) => { const category: string | null | undefined = get('event.category[0]', ecs); const action: string | null | undefined = get('event.action[0]', ecs); + const dataset: string | null | undefined = get('event.dataset[0]', ecs); return ( - category != null && - category.toLowerCase() === 'authentication' && - action != null && - action.toLowerCase() === actionName + (category?.toLowerCase() === 'authentication' || + dataset?.toLowerCase() === 'endpoint.events.security') && + action?.toLowerCase() === actionName ); }, renderRow: ({ browserFields, data, timelineId }) => ( @@ -234,6 +233,11 @@ const endgameProcessStartedRowRenderer = createEndgameProcessRowRenderer({ text: i18n.PROCESS_STARTED, }); +const endpointProcessStartRowRenderer = createEndgameProcessRowRenderer({ + actionName: 'start', + text: i18n.PROCESS_STARTED, +}); + const systemProcessStoppedRowRenderer = createGenericFileRowRenderer({ actionName: 'process_stopped', text: i18n.PROCESS_STOPPED, @@ -244,11 +248,21 @@ const endgameProcessTerminationRowRenderer = createEndgameProcessRowRenderer({ text: i18n.TERMINATED_PROCESS, }); +const endpointProcessEndRowRenderer = createEndgameProcessRowRenderer({ + actionName: 'end', + text: i18n.TERMINATED_PROCESS, +}); + const endgameFileCreateEventRowRenderer = createFimRowRenderer({ actionName: 'file_create_event', text: i18n.CREATED_FILE, }); +const endpointFileCreationEventRowRenderer = createFimRowRenderer({ + actionName: 'creation', + text: i18n.CREATED_FILE, +}); + const fimFileCreateEventRowRenderer = createFimRowRenderer({ actionName: 'created', text: i18n.CREATED_FILE, @@ -259,6 +273,11 @@ const endgameFileDeleteEventRowRenderer = createFimRowRenderer({ text: i18n.DELETED_FILE, }); +const endpointFileDeletionEventRowRenderer = createFimRowRenderer({ + actionName: 'deletion', + text: i18n.DELETED_FILE, +}); + const fimFileDeletedEventRowRenderer = createFimRowRenderer({ actionName: 'deleted', text: i18n.DELETED_FILE, @@ -284,6 +303,11 @@ const endgameIpv4ConnectionAcceptEventRowRenderer = createSocketRowRenderer({ text: i18n.ACCEPTED_A_CONNECTION_VIA, }); +const endpointConnectionAcceptedEventRowRenderer = createSocketRowRenderer({ + actionName: 'connection_accepted', + text: i18n.ACCEPTED_A_CONNECTION_VIA, +}); + const endgameIpv6ConnectionAcceptEventRowRenderer = createSocketRowRenderer({ actionName: 'ipv6_connection_accept_event', text: i18n.ACCEPTED_A_CONNECTION_VIA, @@ -294,6 +318,11 @@ const endgameIpv4DisconnectReceivedEventRowRenderer = createSocketRowRenderer({ text: i18n.DISCONNECTED_VIA, }); +const endpointDisconnectReceivedEventRowRenderer = createSocketRowRenderer({ + actionName: 'disconnect_received', + text: i18n.DISCONNECTED_VIA, +}); + const endgameIpv6DisconnectReceivedEventRowRenderer = createSocketRowRenderer({ actionName: 'ipv6_disconnect_received_event', text: i18n.DISCONNECTED_VIA, @@ -315,6 +344,10 @@ const endgameUserLogonRowRenderer = createSecurityEventRowRenderer({ actionName: 'user_logon', }); +const endpointUserLogOnRowRenderer = createSecurityEventRowRenderer({ + actionName: 'log_on', +}); + const dnsRowRenderer = createDnsRowRenderer(); const systemExistingUserRowRenderer = createGenericSystemRowRenderer({ @@ -357,6 +390,10 @@ const systemLogoutRowRenderer = createGenericSystemRowRenderer({ text: i18n.LOGGED_OUT, }); +const endpointUserLogOffRowRenderer = createSecurityEventRowRenderer({ + actionName: 'log_off', +}); + const systemProcessErrorRowRenderer = createGenericFileRowRenderer({ actionName: 'process_error', text: i18n.PROCESS_ERROR, @@ -408,15 +445,22 @@ export const systemRowRenderers: RowRenderer[] = [ endgameAdminLogonRowRenderer, endgameExplicitUserLogonRowRenderer, endgameFileCreateEventRowRenderer, + endpointFileCreationEventRowRenderer, endgameFileDeleteEventRowRenderer, + endpointFileDeletionEventRowRenderer, endgameIpv4ConnectionAcceptEventRowRenderer, + endpointConnectionAcceptedEventRowRenderer, endgameIpv6ConnectionAcceptEventRowRenderer, endgameIpv4DisconnectReceivedEventRowRenderer, + endpointDisconnectReceivedEventRowRenderer, endgameIpv6DisconnectReceivedEventRowRenderer, endgameProcessStartedRowRenderer, + endpointProcessStartRowRenderer, endgameProcessTerminationRowRenderer, + endpointProcessEndRowRenderer, endgameUserLogoffRowRenderer, endgameUserLogonRowRenderer, + endpointUserLogOnRowRenderer, fimFileCreateEventRowRenderer, fimFileDeletedEventRowRenderer, systemAcceptedRowRenderer, @@ -431,6 +475,7 @@ export const systemRowRenderers: RowRenderer[] = [ systemInvalidRowRenderer, systemLoginRowRenderer, systemLogoutRowRenderer, + endpointUserLogOffRowRenderer, systemPackageInstalledRowRenderer, systemPackageUpdatedRowRenderer, systemPackageRemovedRowRenderer, diff --git a/x-pack/plugins/security_solution/server/search_strategy/timeline/factory/events/all/constants.ts b/x-pack/plugins/security_solution/server/search_strategy/timeline/factory/events/all/constants.ts index 649a36d01d47d..5e9391df5b8a4 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/timeline/factory/events/all/constants.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/timeline/factory/events/all/constants.ts @@ -162,9 +162,12 @@ export const TIMELINE_EVENTS_FIELDS = [ 'tls.server_certificate.fingerprint.sha1', 'user.domain', 'winlog.event_id', + 'process.exit_code', 'process.hash.md5', 'process.hash.sha1', 'process.hash.sha256', + 'process.parent.name', + 'process.parent.pid', 'process.pid', 'process.name', 'process.ppid',