Skip to content

Commit 15bebbd

Browse files
Display multiple copyable fields for process.args in resolver node detail panel
1 parent 2903844 commit 15bebbd

4 files changed

Lines changed: 38 additions & 11 deletions

File tree

x-pack/plugins/security_solution/common/endpoint/models/event.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,12 @@ export function md5HashForProcess(event: SafeResolverEvent): string | undefined
160160
/**
161161
* First non-null value for the `event.process.args` field.
162162
*/
163-
export function argsForProcess(event: SafeResolverEvent): string | undefined {
163+
export function argsForProcess(event: SafeResolverEvent): string[] | undefined {
164164
if (isLegacyEventSafeVersion(event)) {
165165
// There is not currently a key for this on Legacy event types
166166
return undefined;
167167
}
168-
return firstNonNullValue(event.process?.args);
168+
return values(event.process?.args);
169169
}
170170

171171
/**

x-pack/plugins/security_solution/public/resolver/mocks/endpoint_event.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export function mockEndpointEvent({
5151
process: {
5252
entity_id: entityID,
5353
executable: 'executable',
54-
args: 'args',
54+
args: ['args0', 'args1', 'args2'],
5555
name: processName,
5656
pid,
5757
hash: {

x-pack/plugins/security_solution/public/resolver/view/panel.test.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,18 @@ describe(`Resolver: when analyzing a tree with no ancestors and two children and
3434
/**
3535
* These are the details we expect to see in the node detail view when the origin is selected.
3636
*/
37-
const originEventDetailEntries: ReadonlyMap<string, string> = new Map([
37+
const originEventDetailEntries: Array<[string, string]> = [
3838
['@timestamp', 'Sep 23, 2020 @ 08:25:32.316'],
3939
['process.executable', 'executable'],
4040
['process.pid', '0'],
4141
['user.name', 'user.name'],
4242
['user.domain', 'user.domain'],
4343
['process.parent.pid', '0'],
4444
['process.hash.md5', 'hash.md5'],
45-
['process.args', 'args'],
46-
]);
45+
['process.args', 'args0'],
46+
['process.args', 'args1'],
47+
['process.args', 'args2'],
48+
];
4749

4850
beforeEach(() => {
4951
// create a mock data access layer
@@ -129,11 +131,16 @@ describe(`Resolver: when analyzing a tree with no ancestors and two children and
129131
describe.each([...originEventDetailEntries])(
130132
'when the user hovers over the description for the field (%p) with their mouse',
131133
(fieldTitleText, value) => {
134+
// If there are multiple values for a field, i.e. an array, this is the index for the value we are testing.
135+
const entryIndex = originEventDetailEntries
136+
.filter(([fieldName]) => fieldName === fieldTitleText)
137+
.findIndex(([_, fieldValue]) => fieldValue === value);
132138
beforeEach(async () => {
133139
const dt = await simulator().resolveWrapper(() => {
134140
return simulator()
135141
.testSubject('resolver:node-detail:entry-title')
136-
.filterWhere((title) => title.text() === fieldTitleText);
142+
.filterWhere((title) => title.text() === fieldTitleText)
143+
.at(entryIndex);
137144
});
138145

139146
expect(dt).toHaveLength(1);
@@ -184,7 +191,9 @@ describe(`Resolver: when analyzing a tree with no ancestors and two children and
184191
['user.domain', 'user.domain'],
185192
['process.parent.pid', '0'],
186193
['process.hash.md5', 'hash.md5'],
187-
['process.args', 'args'],
194+
['process.args', 'args0'],
195+
['process.args', 'args1'],
196+
['process.args', 'args2'],
188197
]);
189198
});
190199
});

x-pack/plugins/security_solution/public/resolver/view/panels/node_detail.tsx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,12 @@ const NodeDetailView = memo(function ({
122122
description: eventModel.argsForProcess(processEvent),
123123
};
124124

125-
// This is the data in {title, description} form for the EuiDescriptionList to display
126-
const processDescriptionListData = [
125+
const flattenedEntries: Array<{
126+
title: string;
127+
description: string | string[] | number | undefined;
128+
}> = [];
129+
130+
const flattenedDescriptionListData = [
127131
createdEntry,
128132
pathEntry,
129133
pidEntry,
@@ -132,7 +136,21 @@ const NodeDetailView = memo(function ({
132136
parentPidEntry,
133137
md5Entry,
134138
commandLineEntry,
135-
]
139+
].reduce((flattenedList, entry) => {
140+
if (Array.isArray(entry.description)) {
141+
return [
142+
...flattenedList,
143+
...entry.description.map((value) => {
144+
return { title: entry.title, description: value };
145+
}),
146+
];
147+
} else {
148+
return [...flattenedList, entry];
149+
}
150+
}, flattenedEntries);
151+
152+
// This is the data in {title, description} form for the EuiDescriptionList to display
153+
const processDescriptionListData = flattenedDescriptionListData
136154
.filter((entry) => {
137155
return entry.description !== undefined;
138156
})

0 commit comments

Comments
 (0)