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

[Endpoint] resolver v1 events #59233

Merged

Conversation

kqualters-elastic
Copy link
Contributor

@kqualters-elastic kqualters-elastic commented Mar 3, 2020

Summary

Changes resolver to work with both v0 and v1 events. Also adds some placeholder logic for retrieving the ancestors of a process.

resolver_v1

Copy link
Contributor

@oatkiller oatkiller left a 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(
Copy link
Contributor

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

Copy link
Contributor

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?

Copy link
Contributor

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} />
Copy link
Contributor

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?

Copy link
Contributor Author

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

Copy link
Contributor

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?

Copy link
Contributor

@peluja1012 peluja1012 Mar 13, 2020

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.

Copy link
Contributor Author

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

Copy link
Contributor

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
Copy link
Contributor

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) {
Copy link
Contributor

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) {
Copy link
Contributor

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) {
Copy link
Contributor

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)
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 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;
Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor

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} />
Copy link
Contributor

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>
Copy link
Contributor

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[]>();
Copy link
Contributor

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 },
Copy link
Contributor

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

@kqualters-elastic kqualters-elastic marked this pull request as ready for review March 10, 2020 13:13
@kqualters-elastic kqualters-elastic requested a review from a team as a code owner March 10, 2020 13:13
@kqualters-elastic kqualters-elastic changed the title Task/resolver v1 events [Endpoint] resolver v1 events Mar 10, 2020
@kqualters-elastic kqualters-elastic added the Feature:Endpoint Elastic Endpoint feature label Mar 10, 2020
@elasticmachine
Copy link
Contributor

Pinging @elastic/endpoint-app-team (Feature:Endpoint)

@kqualters-elastic kqualters-elastic added the Team:Endpoint Data Visibility Team managing the endpoint resolver label Mar 10, 2020
@elasticmachine
Copy link
Contributor

Pinging @elastic/endpoint-data-visibility-team (Team:Endpoint Data Visibility)

@kqualters-elastic kqualters-elastic added release_note:skip Skip the PR/issue when compiling release notes v7.7.0 v8.0.0 labels Mar 10, 2020
export function isLegacyEvent(
event: EndpointEvent | LegacyEndpointEvent
): event is LegacyEndpointEvent {
return (event as LegacyEndpointEvent).endgame !== undefined;
Copy link
Contributor

@bkimmel bkimmel Mar 12, 2020

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[];
Copy link
Contributor

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

Copy link
Contributor

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>) {

Copy link
Contributor

@bkimmel bkimmel left a 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;
}
Copy link
Contributor

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?

Copy link
Contributor Author

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?: {
Copy link
Contributor

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?

Copy link
Contributor Author

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[];
Copy link
Contributor

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} />
Copy link
Contributor

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>
Copy link
Contributor

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>
Copy link
Contributor

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;
Copy link
Contributor

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 =
Copy link
Contributor

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) {
Copy link
Contributor

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[];
Copy link
Contributor

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?

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 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

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

History

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

@kqualters-elastic kqualters-elastic merged commit 64af780 into elastic:master Mar 18, 2020
@kqualters-elastic kqualters-elastic deleted the task/resolver-v1-events branch March 18, 2020 17:18
jloleysens added a commit that referenced this pull request Mar 18, 2020
…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)
  ...
jloleysens added a commit to jloleysens/kibana that referenced this pull request Mar 19, 2020
* 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)
  ...
@kibanamachine kibanamachine added the backport missing Added to PRs automatically when the are determined to be missing a backport. label Mar 19, 2020
@kibanamachine
Copy link
Contributor

Friendly reminder: Looks like this PR hasn’t been backported yet.
To create backports run node scripts/backport --pr 59233 or prevent reminders by adding the backport:skip label.

kqualters-elastic added a commit that referenced this pull request Mar 19, 2020
* 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]>
@kibanamachine kibanamachine removed the backport missing Added to PRs automatically when the are determined to be missing a backport. label Mar 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Endpoint Elastic Endpoint feature release_note:skip Skip the PR/issue when compiling release notes Team:Endpoint Data Visibility Team managing the endpoint resolver v7.7.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants