diff --git a/x-pack/plugins/session_view/common/test/mock_data.ts b/x-pack/plugins/session_view/common/test/mock_data.ts
index 3a1b57c9cf764..8426aa2602312 100644
--- a/x-pack/plugins/session_view/common/test/mock_data.ts
+++ b/x-pack/plugins/session_view/common/test/mock_data.ts
@@ -5,51 +5,19 @@
* 2.0.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { EventAction, ProcessEvent } from '../../public/hooks/use_process_tree';
import uuid from 'uuid';
+import { EventAction, ProcessEvent } from '../../public/hooks/use_process_tree';
export const getStart = () => {
- return [{
- '@timestamp': 'Thu Oct 14 2021 12: 06: 48 GMT-0700 (Pacific Daylight Time)',
- event: {
- kind: 'event',
- category: 'process',
- action: EventAction.exec,
- },
- process: {
- args: ['bash'],
- args_count: 1,
- command_line: 'bash',
- entity_id: '4321',
- executable: '/bin/bash',
- name: 'bash',
- interactive: true,
- working_directory: '/home/kg',
- pid: 3,
- pgid: 2,
-
- user: {
- id: '2',
- name: 'kg',
- },
-
- parent: {
- args: ['/bin/sshd'],
- args_count: 1,
- command_line: 'sshd',
- entity_id: '4322',
- executable: '/bin/sshd',
- name: 'sshd',
- interactive: true,
- working_directory: '/',
- pid: 2,
- pgid: 2,
- user: {
- id: '0',
- name: 'root',
- },
+ return [
+ {
+ '@timestamp': 'Thu Oct 14 2021 12: 06: 48 GMT-0700 (Pacific Daylight Time)',
+ event: {
+ kind: 'event',
+ category: 'process',
+ action: EventAction.exec,
},
- session: {
+ process: {
args: ['bash'],
args_count: 1,
command_line: 'bash',
@@ -60,29 +28,63 @@ export const getStart = () => {
working_directory: '/home/kg',
pid: 3,
pgid: 2,
+
user: {
id: '2',
name: 'kg',
},
- },
- entry: {
- args: ['bash'],
- args_count: 1,
- command_line: 'bash',
- entity_id: '4321',
- executable: '/bin/bash',
- name: 'bash',
- interactive: true,
- working_directory: '/home/kg',
- pid: 3,
- pgid: 2,
- user: {
- id: '2',
- name: 'kg',
+
+ parent: {
+ args: ['/bin/sshd'],
+ args_count: 1,
+ command_line: 'sshd',
+ entity_id: '4322',
+ executable: '/bin/sshd',
+ name: 'sshd',
+ interactive: true,
+ working_directory: '/',
+ pid: 2,
+ pgid: 2,
+ user: {
+ id: '0',
+ name: 'root',
+ },
+ },
+ session: {
+ args: ['bash'],
+ args_count: 1,
+ command_line: 'bash',
+ entity_id: '4321',
+ executable: '/bin/bash',
+ name: 'bash',
+ interactive: true,
+ working_directory: '/home/kg',
+ pid: 3,
+ pgid: 2,
+ user: {
+ id: '2',
+ name: 'kg',
+ },
+ },
+ entry: {
+ args: ['bash'],
+ args_count: 1,
+ command_line: 'bash',
+ entity_id: '4321',
+ executable: '/bin/bash',
+ name: 'bash',
+ interactive: true,
+ working_directory: '/home/kg',
+ pid: 3,
+ pgid: 2,
+ user: {
+ id: '2',
+ name: 'kg',
+ },
},
},
},
- }];
+ ];
};
export const getEvent = () => {
@@ -90,94 +92,96 @@ export const getEvent = () => {
{
args: ['ls', '-l'],
command_line: 'ls -l',
- name: 'ls'
+ name: 'ls',
},
{
args: ['pwd'],
command_line: 'pwd',
- name: 'pwd'
+ name: 'pwd',
},
{
args: ['dir'],
command_line: 'dir',
- name: 'dir'
- }
- ]
+ name: 'dir',
+ },
+ ];
const randomElement = random[Math.floor(Math.random() * random.length)];
- return [{
- '@timestamp': 'Thu Oct 14 2021 12: 06: 52 GMT-0700 (Pacific Daylight Time)',
- event: {
- kind: 'event',
- category: 'process',
- action: EventAction.exec,
- },
- process: {
- args: randomElement.args,
- args_count: 2,
- command_line: randomElement.command_line,
- entity_id: uuid.v4().toString(),
- executable: '/bin/ls',
- name: randomElement.name,
- interactive: true,
- working_directory: '/home/kg',
- pid: 4,
- pgid: 3,
- user: {
- id: '2',
- name: 'kg',
+ return [
+ {
+ '@timestamp': 'Thu Oct 14 2021 12: 06: 52 GMT-0700 (Pacific Daylight Time)',
+ event: {
+ kind: 'event',
+ category: 'process',
+ action: EventAction.exec,
},
- parent: {
- args: ['bash'],
- args_count: 1,
- command_line: 'bash',
- entity_id: '4321',
- executable: '/bin/bash',
- name: 'bash',
+ process: {
+ args: randomElement.args,
+ args_count: 2,
+ command_line: randomElement.command_line,
+ entity_id: uuid.v4().toString(),
+ executable: '/bin/ls',
+ name: randomElement.name,
interactive: true,
working_directory: '/home/kg',
- pid: 3,
- pgid: 2,
+ pid: 4,
+ pgid: 3,
user: {
id: '2',
name: 'kg',
},
- },
- session: {
- args: ['bash'],
- args_count: 1,
- command_line: 'bash',
- entity_id: '4321',
- executable: '/bin/bash',
- name: 'bash',
- interactive: true,
- working_directory: '/home/kg',
- pid: 3,
- pgid: 2,
- user: {
- id: '2',
- name: 'kg',
+ parent: {
+ args: ['bash'],
+ args_count: 1,
+ command_line: 'bash',
+ entity_id: '4321',
+ executable: '/bin/bash',
+ name: 'bash',
+ interactive: true,
+ working_directory: '/home/kg',
+ pid: 3,
+ pgid: 2,
+ user: {
+ id: '2',
+ name: 'kg',
+ },
},
- },
- entry: {
- args: ['bash'],
- args_count: 1,
- command_line: 'bash',
- entity_id: '4321',
- executable: '/bin/bash',
- name: 'bash',
- interactive: true,
- working_directory: '/home/kg',
- pid: 3,
- pgid: 2,
- user: {
- id: '2',
- name: 'kg',
+ session: {
+ args: ['bash'],
+ args_count: 1,
+ command_line: 'bash',
+ entity_id: '4321',
+ executable: '/bin/bash',
+ name: 'bash',
+ interactive: true,
+ working_directory: '/home/kg',
+ pid: 3,
+ pgid: 2,
+ user: {
+ id: '2',
+ name: 'kg',
+ },
+ },
+ entry: {
+ args: ['bash'],
+ args_count: 1,
+ command_line: 'bash',
+ entity_id: '4321',
+ executable: '/bin/bash',
+ name: 'bash',
+ interactive: true,
+ working_directory: '/home/kg',
+ pid: 3,
+ pgid: 2,
+ user: {
+ id: '2',
+ name: 'kg',
+ },
},
},
},
- }];
+ ];
};
export const getEnd = () => {
@@ -272,12 +276,12 @@ export const getEnd = () => {
working_directory: '/home/kg',
pid: 6,
pgid: 4,
-
+
user: {
id: '2',
name: 'kg',
},
-
+
parent: {
args: ['df'],
args_count: 1,
@@ -346,12 +350,12 @@ export const getEnd = () => {
working_directory: '/home/kg',
pid: 6,
pgid: 4,
-
+
user: {
id: '2',
name: 'kg',
},
-
+
parent: {
args: ['df'],
args_count: 1,
@@ -422,12 +426,12 @@ export const getEnd = () => {
pgid: 4,
end: 'Thu Oct 14 2021 12: 08: 56 GMT-0700 (Pacific Daylight Time)',
exit_code: 137,
-
+
user: {
id: '2',
name: 'kg',
},
-
+
parent: {
args: ['df'],
args_count: 1,
@@ -479,7 +483,7 @@ export const getEnd = () => {
},
},
];
-}
+};
export const mockData: ProcessEvent[] = [
{
diff --git a/x-pack/plugins/session_view/kibana.json b/x-pack/plugins/session_view/kibana.json
index 4bb9471fe85cc..13bf88487473f 100644
--- a/x-pack/plugins/session_view/kibana.json
+++ b/x-pack/plugins/session_view/kibana.json
@@ -7,7 +7,7 @@
"githubTeam": "security-team"
},
"requiredPlugins": ["data"],
- "requiredBundles": ["kibanaReact"],
+ "requiredBundles": ["kibanaReact", "esUiShared"],
"server": true,
"ui": true
}
diff --git a/x-pack/plugins/session_view/public/components/ProcessTree/index.tsx b/x-pack/plugins/session_view/public/components/ProcessTree/index.tsx
index bf1fe3dd54742..74406bd38bf32 100644
--- a/x-pack/plugins/session_view/public/components/ProcessTree/index.tsx
+++ b/x-pack/plugins/session_view/public/components/ProcessTree/index.tsx
@@ -135,9 +135,9 @@ export const ProcessTree = ({
onProcessSelected={onProcessSelected}
/>
);
- })
+ });
}
- }
+ };
return (
diff --git a/x-pack/plugins/session_view/public/components/ProcessTreeAlerts/index.tsx b/x-pack/plugins/session_view/public/components/ProcessTreeAlerts/index.tsx
index 9294669faf4e8..f3c71b1f4726f 100644
--- a/x-pack/plugins/session_view/public/components/ProcessTreeAlerts/index.tsx
+++ b/x-pack/plugins/session_view/public/components/ProcessTreeAlerts/index.tsx
@@ -49,22 +49,22 @@ export function ProcessTreeAlerts({ alerts }: ProcessTreeAlertsDeps) {
-
+
{name}
-
+
{query}
-
+
{severity}
@@ -72,13 +72,13 @@ export function ProcessTreeAlerts({ alerts }: ProcessTreeAlertsDeps) {
-
+
{event.action}
-
+
diff --git a/x-pack/plugins/session_view/public/components/ProcessTreeNode/index.tsx b/x-pack/plugins/session_view/public/components/ProcessTreeNode/index.tsx
index c48d8e0b9bd2a..a0435a3e8d7b6 100644
--- a/x-pack/plugins/session_view/public/components/ProcessTreeNode/index.tsx
+++ b/x-pack/plugins/session_view/public/components/ProcessTreeNode/index.tsx
@@ -47,7 +47,6 @@ export function ProcessTreeNode({
setChildrenExpanded(isSessionLeader || process.autoExpand);
}, [isSessionLeader, process.autoExpand]);
-
const processDetails = useMemo(() => {
return process.getDetails();
}, [process.events.length]);
@@ -55,17 +54,17 @@ export function ProcessTreeNode({
const hasExec = useMemo(() => {
return process.hasExec();
}, [process.events.length]);
-
+
const alerts = useMemo(() => {
return process.getAlerts();
}, [process.events.length]);
-
+
if (!processDetails) {
return null;
}
-
+
const styles = useStyles({ depth, hasAlerts: !!alerts.length });
-
+
useLayoutEffect(() => {
if (searchMatched !== null && textRef.current) {
const regex = new RegExp(searchMatched);
@@ -108,15 +107,21 @@ export function ProcessTreeNode({
const getExpandedIcon = (expanded: boolean) => {
return expanded ? 'arrowUp' : 'arrowDown';
- }
+ };
const renderButtons = () => {
const buttons = [];
if (!isSessionLeader && process.children.length > 0) {
buttons.push(
- setChildrenExpanded(!childrenExpanded)}>
-
+ setChildrenExpanded(!childrenExpanded)}
+ >
+
);
@@ -124,8 +129,11 @@ export function ProcessTreeNode({
if (alerts.length) {
buttons.push(
- setAlertsExpanded(!alertsExpanded)}>
-
+ setAlertsExpanded(!alertsExpanded)}
+ >
+
);
@@ -142,7 +150,7 @@ export function ProcessTreeNode({
<>
{name || executable}
-
+
{user.name}
>
@@ -189,11 +197,16 @@ export function ProcessTreeNode({
const { user, parent } = processDetails.process;
if (user.name === 'root' && user.id !== parent.user.id) {
- return
-
-
+ return (
+
+
+
+ );
}
- }
+ };
const onProcessClicked = (e: MouseEvent) => {
e.stopPropagation();
diff --git a/x-pack/plugins/session_view/public/components/ProcessTreeNode/styles.ts b/x-pack/plugins/session_view/public/components/ProcessTreeNode/styles.ts
index 7407c2feac680..cdf738531b14b 100644
--- a/x-pack/plugins/session_view/public/components/ProcessTreeNode/styles.ts
+++ b/x-pack/plugins/session_view/public/components/ProcessTreeNode/styles.ts
@@ -26,7 +26,7 @@ export const useStyles = ({ depth, hasAlerts }: StylesDeps) => {
children = 'children',
alerts = 'alerts',
output = 'output',
- userChanged = 'user'
+ userChanged = 'user',
}
const darkText: CSSObject = {
@@ -101,7 +101,7 @@ export const useStyles = ({ depth, hasAlerts }: StylesDeps) => {
*/
const getHighlightColors = () => {
let bgColor = 'none';
- let hoverColor = '#6B5FC6';
+ const hoverColor = '#6B5FC6';
let borderColor = 'transparent';
// TODO: alerts highlight colors
diff --git a/x-pack/plugins/session_view/public/components/SessionView/index.tsx b/x-pack/plugins/session_view/public/components/SessionView/index.tsx
index d1b6e2606995e..949a2dc7f0afa 100644
--- a/x-pack/plugins/session_view/public/components/SessionView/index.tsx
+++ b/x-pack/plugins/session_view/public/components/SessionView/index.tsx
@@ -7,8 +7,10 @@
import React, { useState, useEffect } from 'react';
import { useQuery } from 'react-query';
import { EuiSearchBar, EuiSearchBarOnChangeArgs, EuiEmptyPrompt } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
import { CoreStart } from '../../../../../../src/core/public';
+import { SectionLoading } from '../../shared_imports';
import { ProcessTree } from '../ProcessTree';
import { Process, ProcessEvent } from '../../hooks/use_process_tree';
import { useStyles } from './styles';
@@ -62,14 +64,16 @@ export const SessionView = ({ sessionEntityId, height }: SessionViewDeps) => {
}
};
- const { data: getData } = useQuery(
- ['process-tree', 'process_tree'],
- () =>
- http.get(PROCESS_EVENTS_ROUTE, {
- query: {
- sessionEntityId,
- },
- })
+ const {
+ isLoading,
+ isError,
+ data: getData,
+ } = useQuery(['process-tree', 'process_tree'], () =>
+ http.get(PROCESS_EVENTS_ROUTE, {
+ query: {
+ sessionEntityId,
+ },
+ })
);
const sortEvents = (a: ProcessEvent, b: ProcessEvent) => {
@@ -106,14 +110,29 @@ export const SessionView = ({ sessionEntityId, height }: SessionViewDeps) => {
);
};
- if (!data.length) {
- return renderNoData();
- }
-
- return (
- <>
-
- {data && (
+ const renderProcessTree = () => {
+ if (isLoading) {
+ return (
+
+
+
+ );
+ }
+ if (isError) {
+ return (
+ Error loading Session View}
+ body={There was an error loading the Session View.
}
+ />
+ );
+ }
+ if (data) {
+ return (
{
onProcessSelected={onProcessSelected}
/>
- )}
+ );
+ }
+ };
+
+ if (!(isLoading || isError || data.length)) {
+ return renderNoData();
+ }
+
+ return (
+ <>
+
+ {renderProcessTree()}
>
);
};
diff --git a/x-pack/plugins/session_view/public/components/SessionViewPage/index.tsx b/x-pack/plugins/session_view/public/components/SessionViewPage/index.tsx
index cadfcdafe7b4e..9479aa252ede8 100644
--- a/x-pack/plugins/session_view/public/components/SessionViewPage/index.tsx
+++ b/x-pack/plugins/session_view/public/components/SessionViewPage/index.tsx
@@ -52,7 +52,6 @@ export const SessionViewPage = (props: RouteComponentProps) => {
}
}, [data]);
-
return (
diff --git a/x-pack/plugins/session_view/public/hooks/use_process_tree.ts b/x-pack/plugins/session_view/public/hooks/use_process_tree.ts
index dd6f02ba24477..4414f4728d865 100644
--- a/x-pack/plugins/session_view/public/hooks/use_process_tree.ts
+++ b/x-pack/plugins/session_view/public/hooks/use_process_tree.ts
@@ -89,7 +89,7 @@ export interface ProcessEvent {
original_time: Date;
original_event: {
action: string;
- },
+ };
rule: {
category: string;
consumer: string;
@@ -100,9 +100,9 @@ export interface ProcessEvent {
risk_score: number;
severity: string;
uuid: string;
- }
- }
- }
+ };
+ };
+ };
}
export interface Process {
@@ -146,7 +146,7 @@ class ProcessImpl implements Process {
hasAlerts() {
return !!this.events.find(({ event }) => event.kind === EventKind.signal);
}
-
+
getAlerts() {
return this.events.filter(({ event }) => event.kind === EventKind.signal);
}
@@ -160,12 +160,14 @@ class ProcessImpl implements Process {
}
getDetails() {
- const execsForks = this.events.filter(({ event }) => event.action === EventAction.exec || event.action === EventAction.fork);
+ const execsForks = this.events.filter(
+ ({ event }) => event.action === EventAction.exec || event.action === EventAction.fork
+ );
if (execsForks.length === 0) {
debugger;
}
-
+
return execsForks[execsForks.length - 1];
}
@@ -206,16 +208,16 @@ export const useProcessTree = ({
// we add a fake session leader event, sourced from wide event data.
// this is because we might not always have a session leader event
// especially if we are paging in reverse from deep within a large session
- const fakeLeaderEvent = forward.find(event => event.event.kind === EventKind.event);
+ const fakeLeaderEvent = forward.find((event) => event.event.kind === EventKind.event);
const sessionLeaderProcess = new ProcessImpl(sessionEntityId);
-
+
if (fakeLeaderEvent) {
- fakeLeaderEvent.process = { ...fakeLeaderEvent.process, ...fakeLeaderEvent.process.entry};
+ fakeLeaderEvent.process = { ...fakeLeaderEvent.process, ...fakeLeaderEvent.process.entry };
sessionLeaderProcess.events.push(fakeLeaderEvent);
}
const initializedProcessMap: ProcessMap = {
- [sessionEntityId]: sessionLeaderProcess,
+ [sessionEntityId]: sessionLeaderProcess,
};
const [processMap, setProcessMap] = useState(initializedProcessMap);
diff --git a/x-pack/plugins/session_view/public/shared_imports.ts b/x-pack/plugins/session_view/public/shared_imports.ts
new file mode 100644
index 0000000000000..0a087e1ac36ae
--- /dev/null
+++ b/x-pack/plugins/session_view/public/shared_imports.ts
@@ -0,0 +1,8 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export { SectionLoading } from '../../../../src/plugins/es_ui_shared/public';
diff --git a/x-pack/plugins/session_view/server/routes/process_events_route.ts b/x-pack/plugins/session_view/server/routes/process_events_route.ts
index 5d53ebf67d096..10c0954f6ad07 100644
--- a/x-pack/plugins/session_view/server/routes/process_events_route.ts
+++ b/x-pack/plugins/session_view/server/routes/process_events_route.ts
@@ -21,7 +21,7 @@ export const registerProcessEventsRoute = (router: IRouter) => {
},
async (context, request, response) => {
const client = context.core.elasticsearch.client.asCurrentUser;
-
+
// TODO: would be good to figure out how to add securitySolution as a dep
// and make use of this way of getting the siem-signals index, instead of
// hardcoding it.
@@ -40,7 +40,7 @@ export const registerProcessEventsRoute = (router: IRouter) => {
},
size: PROCESS_EVENTS_PER_PAGE,
sort: [{ '@timestamp': 'asc' }],
- }
+ },
});
// temporary approach. ideally we'd pull from both these indexes above, but unfortunately
@@ -52,7 +52,7 @@ export const registerProcessEventsRoute = (router: IRouter) => {
body: {
size: PROCESS_EVENTS_PER_PAGE,
sort: [{ '@timestamp': 'asc' }],
- }
+ },
});
alerts.body.hits.hits = alerts.body.hits.hits.map((hit: any) => {
diff --git a/x-pack/plugins/session_view/server/routes/recent_session_route.ts b/x-pack/plugins/session_view/server/routes/recent_session_route.ts
index 6eb1b415f9002..62e92cb98e8b0 100644
--- a/x-pack/plugins/session_view/server/routes/recent_session_route.ts
+++ b/x-pack/plugins/session_view/server/routes/recent_session_route.ts
@@ -32,9 +32,7 @@ export const registerRecentSessionRoute = (router: IRouter) => {
},
},
size: 1,
- sort: [
- {'@timestamp' :'desc'}
- ],
+ sort: [{ '@timestamp': 'desc' }],
},
});
diff --git a/x-pack/plugins/session_view/server/routes/test_route.ts b/x-pack/plugins/session_view/server/routes/test_route.ts
index 2906548f1562a..68b6561cd218e 100644
--- a/x-pack/plugins/session_view/server/routes/test_route.ts
+++ b/x-pack/plugins/session_view/server/routes/test_route.ts
@@ -27,7 +27,7 @@ export const registerTestRoute = (router: IRouter) => {
const { index } = request.query;
const search = await client.search({
- index: [`${index}`]
+ index: [`${index}`],
});
return response.ok({ body: search.body.hits });
@@ -59,7 +59,7 @@ export const registerTestRoute = (router: IRouter) => {
timestamp: new Date().toISOString(),
},
});
- })
+ });
await Promise.all(requests);
@@ -76,7 +76,7 @@ export const registerTestRoute = (router: IRouter) => {
path: INTERNAL_TEST_ROUTE,
validate: {
body: schema.object({
- index: schema.string()
+ index: schema.string(),
}),
},
},
@@ -84,18 +84,18 @@ export const registerTestRoute = (router: IRouter) => {
const { index } = request.body;
const client = context.core.elasticsearch.client.asCurrentUser;
- await client.deleteByQuery({
+ await client.deleteByQuery({
index,
body: {
query: { match_all: {} },
},
});
-
+
return response.ok({
body: {
message: 'ok!',
},
});
- },
- )
+ }
+ );
};