Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution] Use session view plugin to render session viewer in alerts, events and timeline #127520

Merged
merged 29 commits into from
Mar 29, 2022

Conversation

kqualters-elastic
Copy link
Contributor

@kqualters-elastic kqualters-elastic commented Mar 10, 2022

Summary

This pr adds the session view component to the actions component used by both data grid based tables in the alerts, hosts, network external events and rule based tables as well as the timeline flyout component. A new hook useSessionView contains most of the logic for handling timeline tabs, full screen functionality, etc, and existing patterns used for the tab.

Hosts page:
image
Sessions page:
image
Active timeline:
image
Active timeline fullscreen:
image
Alert flyout being opened from session view:
session_view_flyout

There is an active issue with the full screen behavior outside of the timeline flyout, we will need to figure out a way to not hardcode the height of the session view component to be 500px that it currently is, as it is not quite fullscreen.

Also added a feature flag in the kibana advanced settings, this setting defaults to true, and if turned off, makes it so that the button is no longer accessible in the leading control columns and can't be used to render the plugin, making it a feature flag. Easy to remove if we don't want to do that and just want the endpoint configuration to be the feature flag.

Checklist

Delete any items that are not applicable to this PR.

@kqualters-elastic kqualters-elastic added release_note:skip Skip the PR/issue when compiling release notes backport:skip This commit does not require backporting v8.2.0 labels Mar 10, 2022
);
const graphOverlay = useMemo(() => {
const shouldShowOverlay =
(graphEventId != null && graphEventId.length > 0) || sessionViewId !== null;
Copy link
Contributor

@michaelolo24 michaelolo24 Mar 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need graphEventId.length > 0 ? Can we get away with shouldShowOverlay = graphEventId ?? sessionViewId?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we unify the != and !== approach in this statement just to use one? Could be graphEventId or sessionViewId as undefined?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm nervous to change it, for whatever reason, graph event id is set to empty string sometimes and is undefined at other times

(state) => (getTimeline(state, timelineId) ?? timelineDefaults).sessionViewId
);
const sessionViewMain = useMemo(() => {
return sessionViewId !== null ? sessionView.getSessionView(sessionViewId) : null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any situation where it can be undefined? Would we want sessionViewId != null?

@@ -219,7 +240,18 @@ const GraphOverlayComponent: React.FC<OwnProps> = ({ timelineId }) => {
[defaultDataView.patternList, isInTimeline, timelinePatterns]
);

if (fullScreen && !isInTimeline) {
if (!isInTimeline && sessionViewId !== null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need the fullScreen check here anymore?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How it should behave in the fullScreen mode?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like analyzer i think, which it does, we just have a small issue with the hard coded unless specified height of 500px coming from here https://github.com/elastic/kibana/blob/main/x-pack/plugins/session_view/public/components/session_view/styles.ts#L16 @zizhouW @mitodrummer @opauloh I think we should change the styles here so that the search bar/detail panel button take up as much space as the constituent components need, and then the process tree grows to fill the remaining part of a top level container. Passing a height will be buggy/hard for no reason with the full screen functionality in data grid/timeline I think. What do y'all think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, the current way it works, it can't have auto height, because of infinite scrolling, so in order to enable full screen you would need to manually change the height you're passing to SessionView on FullScreen mode, something like this:

sessionView.getSessionView({
   sessionEntityId,
   height: fullScreen ? 'calc(100vh - 118px)' : '500px'
}) 

but having to know the height of the SessionView's search bar (118px), and the default height of the session view (500px) isn't ideal, so we are willing to change later to something more like this

sessionView.getSessionView({
   sessionEntityId,
   isFullScreen: fullScreen
}) 

const { process } = ecsData;
const entryLeaderIds = process?.entry_leader?.entity_id;
if (entryLeaderIds !== undefined) {
return entryLeaderIds[0];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always going to be the first one? And it's guaranteed to be an array of 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, but that's exactly why I wanted to get ecs changes in and then use real endpoint data to verify first. Seems to be the case so far.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to check array length at least.

} else {
return null;
}
}, [ecsData]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't expect ecsData to change, but any thoughts on this being ecsData.process?.entry_leader?.entity_id to be more specific? Not sure it would make a difference or if the linter would take it, but just a suggestion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, the better is to have a more specific to check.

<EuiButtonIcon
aria-label={i18n.VIEW_DETAILS_FOR_ROW({ ariaRowindex, columnValues })}
data-test-subj="session-view-button"
iconType="console"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any word on when they expect the icon in the mocks to be added to eui?

Copy link
Contributor

@opauloh opauloh Mar 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the Icons are merged in Eui, and it seems we will have a quick release today 🤞 or at most tomorrow

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pr here #128313

}

const SessionTabContent: React.FC<Props> = ({ timelineId }) => {
const { sessionView } = useKibana().services;
Copy link
Contributor

@michaelolo24 michaelolo24 Mar 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if you can just have a useSessionView hook that internalizes all this logic and you can use that here and in the graph_overlay component https://github.com/elastic/kibana/pull/127520/files#diff-76ce75e94a9924487bf7b684f4a7404b250414469330abfbbf6ab0d34e770597, and you can just test that hook once.

@@ -262,33 +273,36 @@ const TabsContentComponent: React.FC<BasicTimelineTab> = ({
[appNotes, allTimelineNoteIds, timelineDescription]
);

const setActiveTab = useCallback(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. ❤️

@@ -287,6 +287,46 @@ export const updateGraphEventId = ({
};
};

export const updateSessionViewEventId = ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will these two ever be different? Could updateSessionViewEventId and updateSessionViewSessionId be combined, or will they just be different in the future? It might be better to just leave them as one combined action to save a state update and then break them apart in the future if/when it's necessary

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++ what @michaelolo24 suggests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was placeholder stuff while I was testing if we could use entry_leader.entity_id in place of session_leader.entity_id etc, removing.

const sessionIsInteractive = !!tty;

return sessionIsInteractive && parentIsASessionLeader && processIsAGroupLeader;
return !!(sessionIsInteractive && parentIsASessionLeader && processIsAGroupLeader);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch

@@ -170,15 +170,16 @@ export class ProcessImpl implements Process {
// to be used as a source for the most up to date details
// on the processes lifecycle.
getDetailsMemo = memoizeOne((events: ProcessEvent[]) => {
// TODO: add these to generator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make an issue and do it in a separate PR? Thanks!

@YulNaumenko YulNaumenko self-requested a review March 23, 2022 00:46
const actionsToFind = [EventAction.fork, EventAction.exec, EventAction.end];
const filtered = events.filter((processEvent) => {
return actionsToFind.includes(processEvent.event.action);
return true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we still need that filter?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the this.events array contains all events for a particular process, which can include many event.action. e.g fork, exec, end, session_id_change, uid_change, etc... Not only that but any alert events will be stored in this.events as well (something we plan to break out into it's own this.alerts array). I assume this change was done while testing mock data perhaps? I believe @zizhouW will be making changes here regardless soon.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth updating process_events_route.ts to filter out the event.action types we don't need. like uid_change, gid_change, session_id_change etc... if we do that and store alerts in it's own array then we can do away with this filter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya exactly this change is not intended to be kept, was just for working with mock data

@kqualters-elastic kqualters-elastic requested review from a team as code owners March 29, 2022 08:10
Copy link
Contributor

@opauloh opauloh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

[graphEventId, id]
);

const { DetailsPanel, SessionView, Navigation } = useSessionView({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works, not sure if DetailsPanel and SessionView should be tied together like this, but I would have to think about it more...

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
securitySolution 3006 3009 +3

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
securitySolution 4.8MB 4.8MB +7.6KB
sessionView 51.6KB 51.8KB +192.0B
total +7.8KB

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
sessionView 0 1 +1

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
securitySolution 250.1KB 250.4KB +279.0B
timelines 286.3KB 286.4KB +31.0B
total +310.0B
Unknown metric groups

async chunk count

id before after diff
securitySolution 23 24 +1

ESLint disabled in files

id before after diff
apm 15 14 -1
osquery 5 4 -1
securitySolution 69 68 -1
uptime 7 6 -1
total -4

ESLint disabled line counts

id before after diff
apm 88 85 -3
enterpriseSearch 9 7 -2
fleet 47 46 -1
osquery 122 119 -3
securitySolution 440 441 +1
uptime 49 43 -6
total -14

References to deprecated APIs

id before after diff
canvas 70 64 -6
dashboard 78 72 -6
data 475 465 -10
dataEnhanced 55 49 -6
discover 26 20 -6
fleet 20 19 -1
lens 18 14 -4
management 2 1 -1
maps 456 330 -126
monitoring 40 28 -12
upgradeAssistant 12 7 -5
visDefaultEditor 205 155 -50
visTypeVega 4 3 -1
visualizations 17 13 -4
total -238

Total ESLint disabled count

id before after diff
apm 103 99 -4
enterpriseSearch 9 7 -2
fleet 55 54 -1
osquery 127 123 -4
uptime 56 49 -7
total -18

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

<TestProviders>
<GraphOverlay timelineId={TimelineId.test} />
<GraphOverlay timelineId={TimelineId.test} SessionView={<div />} Navigation={<div />} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would set amockSessionView and mockNavigation so it's easier to change in the future

@@ -34,6 +34,11 @@ export const useStyles = ({ height = 500 }: StylesDeps) => {
zIndex: 2,
};

const nonGrowGroup: CSSObject = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be removed now

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@opauloh can you help us remove this in a follow up PR or coordinate with @kqualters-elastic on removing this? Thanks!

Copy link
Contributor

@michaelolo24 michaelolo24 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for getting this done! Please let's create an issue with some bugs that we found regarding the event.process thing and please add beta tag in a follow up pr as well

Copy link
Contributor

@YulNaumenko YulNaumenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@kqualters-elastic kqualters-elastic merged commit 33b85f8 into elastic:main Mar 29, 2022
@michaelolo24 michaelolo24 added release_note:feature Makes this part of the condensed release notes and removed release_note:skip Skip the PR/issue when compiling release notes labels Mar 29, 2022
@@ -140,7 +151,8 @@ const ActiveTimelineTab = memo<ActiveTimelineTabProps>(
);

const isGraphOrNotesTabs = useMemo(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably make this more descriptive in a follow up since it's scope has expanded. Or add a comment to it's use case

activeTab: TimelineTabs;
}

const NavigationComponent: React.FC<NavigationProps> = ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should separate each of these into their own files when there's time and create test for each of them

timelineId,
timelineFullScreen,
toggleFullScreen,
graphEventId,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not being used

timelineId: TimelineId;
timelineFullScreen: boolean;
toggleFullScreen: () => void;
graphEventId?: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not used

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting ci:cloud-deploy Create or update a Cloud deployment release_note:feature Makes this part of the condensed release notes Team: AWP: Platform Adaptive Workload Protection Platform team from Security Solution Team:Threat Hunting:Investigations Security Solution Investigations Team v8.2.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants