-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[Security Solution] Use session view plugin to render session viewer in alerts, events and timeline #127520
Conversation
); | ||
const graphOverlay = useMemo(() => { | ||
const shouldShowOverlay = | ||
(graphEventId != null && graphEventId.length > 0) || sessionViewId !== null; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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]; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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]); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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" |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
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 = ({ |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++ what @michaelolo24 suggests
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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!
const actionsToFind = [EventAction.fork, EventAction.exec, EventAction.end]; | ||
const filtered = events.filter((processEvent) => { | ||
return actionsToFind.includes(processEvent.event.action); | ||
return true; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this 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({ |
There was a problem hiding this comment.
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...
💚 Build SucceededMetrics [docs]Module Count
Async chunks
Public APIs missing exports
Page load bundle
Unknown metric groupsasync chunk count
ESLint disabled in files
ESLint disabled line counts
References to deprecated APIs
Total ESLint disabled count
History
To update your PR or re-run it, just comment with: |
<TestProviders> | ||
<GraphOverlay timelineId={TimelineId.test} /> | ||
<GraphOverlay timelineId={TimelineId.test} SessionView={<div />} Navigation={<div />} /> |
There was a problem hiding this comment.
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 = { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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!
There was a problem hiding this 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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@@ -140,7 +151,8 @@ const ActiveTimelineTab = memo<ActiveTimelineTabProps>( | |||
); | |||
|
|||
const isGraphOrNotesTabs = useMemo( |
There was a problem hiding this comment.
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> = ({ |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not used
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:
Sessions page:
Active timeline:
Active timeline fullscreen:
Alert flyout being opened from session view:
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.