-
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
[Endpoint] resolver v1 events #59233
[Endpoint] resolver v1 events #59233
Conversation
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.
Other than the comments in here, let's talk about refactoring the middleware before merge
} | ||
|
||
export type ResolverEvent = EndpointEvent | LegacyEndpointEvent; | ||
|
||
export function isLegacyEvent( |
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.
Would you plz move this out of types
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.
❔ If its sole purpose seems to be as a type discriminant, where should it go? A selector?
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 think 'model' would be good. I'd say 'no' to selector as it doesn't take global state as its only param (doesn't take it at all).
content: ( | ||
<> | ||
<EuiSpacer /> | ||
<AlertDetailResolver selectedEvent={(alertDetailsData as unknown) as ResolverEvent} /> |
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 is this unsafe cast needed? can we work out a way to remove it?
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.
imo we should get rid of the AlertData type, as it's really just a variation of an EndpointEvent
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.
does removing the cast change anything then?
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.
@oatkiller @kqualters-elastic @marshallmain ResolverEvent
is defined as:
ResolverEvent = EndpointEvent | LegacyEndpointEvent;
AlertData
, which alertDetailsData
is a type of, is defined as:
export type AlertData = AlertEvent & AlertMetadata;
We have malware_event
, network
, process
, and registry
ECS schemas defined here: https://github.com/elastic/endpoint-app-team/tree/master/schemas/v1
Does it make sense to model our types after these schemas? If so, I think our AlertEvent
type should follow the malware_event
ECS and our EndpointEvent
type should probably be a union of a new ProcessEvent
type and our existing AlertEvent
.
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.
yes agreed, wouldn't hurt to support LegacyEndpointEvent
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.
I think that adds up. That being said, if malware_event, network, process, and registry are in the same index, I don't see why they shouldn't be the same schema. In fact, I don't see why ECS shouldn't just be a single schema. Its not Elastic Common Schemas is it?
@@ -33,4 +33,6 @@ export const AlertDetailResolver = styled( | |||
width: 100%; | |||
display: flex; | |||
flex-grow: 1; | |||
// ugly demo hack until can play nice with 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.
If this is still here by the time we merge, let's remove the comment and add a github issue instead
const { | ||
endgame: { event_type_full: type, event_subtype_full: subType }, | ||
} = passedEvent; | ||
export function eventType(passedEvent: ResolverEvent) { |
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.
could you add a return type here?
'processCreated' | 'processRan' | ... etc
} | ||
|
||
/** | ||
* Returns the process event's pid | ||
*/ | ||
export function uniquePidForProcess(event: LegacyEndpointEvent) { | ||
return event.endgame.unique_pid; | ||
export function uniquePidForProcess(event: ResolverEvent) { |
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.
Could you add an explicit return type here
} | ||
|
||
/** | ||
* Returns the process event's parent pid | ||
*/ | ||
export function uniqueParentPidForProcess(event: LegacyEndpointEvent) { | ||
return event.endgame.unique_ppid; | ||
export function uniqueParentPidForProcess(event: ResolverEvent) { |
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.
Could you add an explicit return type here
@@ -48,14 +48,20 @@ export const Panel = memo(function Event({ className }: { className?: string }) | |||
() => | |||
[...processNodePositions.keys()].map(processEvent => { | |||
let dateTime; | |||
if (processEvent.endgame.timestamp_utc) { | |||
const date = new Date(processEvent.endgame.timestamp_utc); | |||
const eventTimestamp = isLegacyEvent(processEvent) |
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 centralize this type of logic into an event model
import { timestamp } from 'models/event'
timestamp(processEvent)
@@ -315,23 +315,34 @@ export interface EndpointEvent { | |||
category: string; | |||
type: string; | |||
id: string; | |||
kind: 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.
❔ At a glance, we have three things (category
, type
, and now kind
) that are basically perfect synonyms. Can we do something to make this type more readable or useful? Either changing from string
to the things that can actually be there, or documenting the differences?
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.
@bkimmel I can link you to the docs that describe the differences. We could use enums I suppose if we wanted but we'd have to update them as ecs changes. I think it'd probably go better the document the differences route.
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.
@bkimmel long term we need a way to keep these types in sync w/ ECS. Part of that should be getting descriptions of each field. In the meantime, getting comments on each field here is on my radar.
<EuiText>Alert Status: Open</EuiText> | ||
<EuiSpacer /> | ||
</section> | ||
<EuiTabbedContent tabs={tabs} initialSelectedTab={tabs[0]} className={className} /> |
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.
🆗 Nice use of EuiTabbedContent
<> | ||
<section className="details-overview-summary"> | ||
<EuiTitle size="s"> | ||
<h3> |
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 think the h3 might be ( ❔ ) redundant but maybe you have to use the size="l"
variant of EUITitle
const idToChildren = new Map<number | undefined, LegacyEndpointEvent[]>(); | ||
const idToValue = new Map<number, LegacyEndpointEvent>(); | ||
export function factory(processes: ResolverEvent[]): IndexedProcessTree { | ||
const idToChildren = new Map<string | undefined, ResolverEvent[]>(); |
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.
🆗 Cool, I didn't know you could use Type directions in constructors that way.
{ | ||
children: [{ lifecycle: childEvents }], | ||
}, | ||
{ events: relatedEvents }, |
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.
❔ Maybe also receive ancestors here instead of setting it above in the let
and pushing to it
Adding string or array for category and type
…s-elastic/kibana into task/resolver-v1-events
Pinging @elastic/endpoint-app-team (Feature:Endpoint) |
Pinging @elastic/endpoint-data-visibility-team (Team:Endpoint Data Visibility) |
export function isLegacyEvent( | ||
event: EndpointEvent | LegacyEndpointEvent | ||
): event is LegacyEndpointEvent { | ||
return (event as LegacyEndpointEvent).endgame !== 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 think you could skip the cast with return 'endgame' in event;
@@ -311,22 +311,27 @@ export interface LegacyEndpointEvent { | |||
export interface EndpointEvent { | |||
'@timestamp': number; | |||
event: { | |||
category: string; | |||
type: string; | |||
category: string | 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.
❔ Should this stuff get typed as readonly
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.
my suggestion is to leave the types in types.ts
as plain as possible. this way, you could use them when constructing a EndpointEvent
. If you need a readonly (or partial, or deepreadonly, or deeppartial, etc) type, you can use a generic type for it. e.g. function takesReadonlyEvent(event: DeepReadonly<EndpointEvent>) {
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.
👍 with a couple ❔
const alertDetailsData = useAlertListSelector(selectors.selectedAlertDetailsData); | ||
if (alertDetailsData === undefined) { | ||
return 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.
Could you please remove the selectedAlertIsLegacyEndpointEvent
selector if it's no longer used?
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.
done
@@ -328,6 +328,10 @@ export interface EndpointEvent { | |||
name: string; | |||
parent?: { | |||
entity_id: string; | |||
parent?: { |
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 do we need process.parent.parent?
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, not sure how this was added. bad merge or something. removing.
@@ -311,22 +311,27 @@ export interface LegacyEndpointEvent { | |||
export interface EndpointEvent { | |||
'@timestamp': number; | |||
event: { | |||
category: string; | |||
type: string; | |||
category: string | 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.
my suggestion is to leave the types in types.ts
as plain as possible. this way, you could use them when constructing a EndpointEvent
. If you need a readonly (or partial, or deepreadonly, or deeppartial, etc) type, you can use a generic type for it. e.g. function takesReadonlyEvent(event: DeepReadonly<EndpointEvent>) {
content: ( | ||
<> | ||
<EuiSpacer /> | ||
<AlertDetailResolver selectedEvent={(alertDetailsData as unknown) as ResolverEvent} /> |
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 think that adds up. That being said, if malware_event, network, process, and registry are in the same index, I don't see why they shouldn't be the same schema. In fact, I don't see why ECS shouldn't just be a single schema. Its not Elastic Common Schemas is it?
</EuiText> | ||
<EuiSpacer /> | ||
<EuiText> | ||
Endpoint Status: <EuiHealth color="success">Online</EuiHealth> |
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.
Would you please i18n this?
<EuiText> | ||
Endpoint Status: <EuiHealth color="success">Online</EuiHealth> | ||
</EuiText> | ||
<EuiText>Alert Status: Open</EuiText> |
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.
Would you please i18n this?
@@ -33,7 +33,7 @@ interface UserChangedSelectedEvent { | |||
/** | |||
* Optional because they could have unselected the event. | |||
*/ | |||
selectedEvent?: LegacyEndpointEvent; | |||
selectedEvent?: ResolverEvent; |
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.
could you please mark this as readonly
for consisency
@@ -275,4 +275,12 @@ export interface SideEffectSimulator { | |||
mock: jest.Mocked<Omit<SideEffectors, 'ResizeObserver'>> & Pick<SideEffectors, 'ResizeObserver'>; | |||
} | |||
|
|||
export type ResolverProcessType = |
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.
would you please add a doc comment here
@@ -19,22 +21,51 @@ export const resolverMiddlewareFactory: MiddlewareFactory = context => { | |||
return api => next => async (action: ResolverAction) => { | |||
next(action); | |||
if (action.type === 'userChangedSelectedEvent') { | |||
if (context?.services.http) { | |||
if (context?.services.http && action.payload.selectedEvent) { |
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.
would you please add a comment generally explaining this? Maybe:
/**
* concurrently fetches a process's details, its ancestors, and its related events.
*/
category: string; | ||
type: string; | ||
category: string | string[]; | ||
type: string | 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.
when would category and type be string arrays?
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 exactly when this is the case, I believe some events can have more than one of each in the case where it was hard to bucket into exactly one existing ECS value. @jonathan-buttner could probably tell you in more detail, this comes from kqualters-elastic#1
💚 Build SucceededHistory
To update your PR or re-run it, just comment with: |
…nless * 'app/painless' of github.com:elastic/kibana: (64 commits) Fix filter scope in bool query (#60488) change index pattern id to be the same as index pattern title (#60436) [Endpoint] resolver v1 events (#59233) Branding fixes for dashboard, loader and space selector (#60073) skip flaky suite (#60535) [SIEM][Detection Engine] Fixes bug with timeline templates not working Fixed errors which are happening if switch between alert types (#60453) [EPM] Add mapping field types to index template generation v2 (#60266) [NP] Cutover ensureDefaultIndexPattern to kibana_utils (#59895) Closes #60265. Adds Beta badge to service map (#60482) [Visualize] Duplicated query filters in es request (#60106) [ML] Disable functional transform tests Fixes to service map single node banner (#60072) [Uptime] replace fetch with kibana http (#59881) Upgrade @types/node to match Node.js runtime (#60368) [License Management] NP migration (#60250) Fix create alert button from not showing in alerts list (#60444) [SIEM][Case] Update connector through flyout (#60307) add data-test-subj where possible on SO management table (#60226) Enforce `required` presence for value/key validation of `recordOf` and `mapOf`. (#60406) ...
* upstream/app/painless: (66 commits) Another i18n issue Fix i18n Fix filter scope in bool query (elastic#60488) change index pattern id to be the same as index pattern title (elastic#60436) [Endpoint] resolver v1 events (elastic#59233) Branding fixes for dashboard, loader and space selector (elastic#60073) skip flaky suite (elastic#60535) [SIEM][Detection Engine] Fixes bug with timeline templates not working Fixed errors which are happening if switch between alert types (elastic#60453) [EPM] Add mapping field types to index template generation v2 (elastic#60266) [NP] Cutover ensureDefaultIndexPattern to kibana_utils (elastic#59895) Closes elastic#60265. Adds Beta badge to service map (elastic#60482) [Visualize] Duplicated query filters in es request (elastic#60106) [ML] Disable functional transform tests Fixes to service map single node banner (elastic#60072) [Uptime] replace fetch with kibana http (elastic#59881) Upgrade @types/node to match Node.js runtime (elastic#60368) [License Management] NP migration (elastic#60250) Fix create alert button from not showing in alerts list (elastic#60444) [SIEM][Case] Update connector through flyout (elastic#60307) ...
Friendly reminder: Looks like this PR hasn’t been backported yet. |
* Unifying the test index name for resolver and alerts * Endpoint isn't sending the agent field so check for it * Update resolver to use either legacy or ecs events * Use correct format for child events api * Adding string or array for category and type * Add return types to process event models * Create a common/models.ts for common event logic * Decrease resolver min height * Update types to match cli tool * Add a smoke test for resolver rendering nodes, remove unused selector * Add common/models/event * Internationalize some strings, address pr comments Co-authored-by: Jonathan Buttner <[email protected]> Co-authored-by: Jonathan Buttner <[email protected]>
Summary
Changes resolver to work with both v0 and v1 events. Also adds some placeholder logic for retrieving the ancestors of a process.