Skip to content

Commit

Permalink
[Endpoint] Show Policy Status on Host Details using Policy Response A…
Browse files Browse the repository at this point in the history
…PI (elastic#64116)

* Add policyStatus to store + drive UI color/label from status value
* Add Middleware placeholder to handle API call (once available)
  • Loading branch information
paul-tavares committed Apr 27, 2020
1 parent 72e85cc commit d77adb7
Show file tree
Hide file tree
Showing 9 changed files with 349 additions and 11 deletions.
117 changes: 116 additions & 1 deletion x-pack/plugins/endpoint/common/generate_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@

import uuid from 'uuid';
import seedrandom from 'seedrandom';
import { AlertEvent, EndpointEvent, HostMetadata, OSFields, HostFields, PolicyData } from './types';
import {
AlertEvent,
EndpointEvent,
HostFields,
HostMetadata,
OSFields,
PolicyData,
HostPolicyResponse,
HostPolicyResponseActionStatus,
} from './types';
import { factory as policyFactory } from './models/policy_config';

export type Event = AlertEvent | EndpointEvent;
Expand Down Expand Up @@ -486,6 +495,112 @@ export class EndpointDocGenerator {
};
}

/**
* Generates a Host Policy response message
*/
generatePolicyResponse(): HostPolicyResponse {
return {
'@timestamp': new Date().toISOString(),
elastic: {
agent: {
id: 'c2a9093e-e289-4c0a-aa44-8c32a414fa7a',
},
},
ecs: {
version: '1.0.0',
},
event: {
created: '2015-01-01T12:10:30Z',
kind: 'policy_response',
},
agent: {
version: '6.0.0-rc2',
id: '8a4f500d',
},
endpoint: {
artifacts: {
'global-manifest': {
version: '1.2.3',
sha256: 'abcdef',
},
'endpointpe-v4-windows': {
version: '1.2.3',
sha256: 'abcdef',
},
'user-whitelist-windows': {
version: '1.2.3',
sha256: 'abcdef',
},
'global-whitelist-windows': {
version: '1.2.3',
sha256: 'abcdef',
},
},
policy: {
applied: {
version: '1.0.0',
id: '17d4b81d-9940-4b64-9de5-3e03ef1fb5cf',
status: HostPolicyResponseActionStatus.success,
response: {
configurations: {
malware: {
status: HostPolicyResponseActionStatus.success,
concerned_actions: ['download_model', 'workflow', 'a_custom_future_action'],
},
events: {
status: HostPolicyResponseActionStatus.success,
concerned_actions: ['ingest_events_config', 'workflow'],
},
logging: {
status: HostPolicyResponseActionStatus.success,
concerned_actions: ['configure_elasticsearch_connection'],
},
streaming: {
status: HostPolicyResponseActionStatus.success,
concerned_actions: [
'detect_file_open_events',
'download_global_artifacts',
'a_custom_future_action',
],
},
},
actions: {
download_model: {
status: HostPolicyResponseActionStatus.success,
message: 'model downloaded',
},
ingest_events_config: {
status: HostPolicyResponseActionStatus.success,
message: 'no action taken',
},
workflow: {
status: HostPolicyResponseActionStatus.success,
message: 'the flow worked well',
},
a_custom_future_action: {
status: HostPolicyResponseActionStatus.success,
message: 'future message',
},
configure_elasticsearch_connection: {
status: HostPolicyResponseActionStatus.success,
message: 'some message',
},
detect_file_open_events: {
status: HostPolicyResponseActionStatus.success,
message: 'some message',
},
download_global_artifacts: {
status: HostPolicyResponseActionStatus.success,
message: 'some message',
},
},
},
},
},
},
};
}

private randomN(n: number): number {
return Math.floor(this.random() * n);
}
Expand Down
100 changes: 100 additions & 0 deletions x-pack/plugins/endpoint/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -573,3 +573,103 @@ export type NewPolicyData = NewDatasource & {
}
];
};

/**
* the possible status for actions, configurations and overall Policy Response
*/
export enum HostPolicyResponseActionStatus {
success = 'success',
failure = 'failure',
warning = 'warning',
}

/**
* The details of a given action
*/
interface HostPolicyResponseActionDetails {
status: HostPolicyResponseActionStatus;
message: string;
}

/**
* A known list of possible Endpoint actions
*/
interface HostPolicyResponseActions {
download_model: HostPolicyResponseActionDetails;
ingest_events_config: HostPolicyResponseActionDetails;
workflow: HostPolicyResponseActionDetails;
configure_elasticsearch_connection: HostPolicyResponseActionDetails;
configure_kernel: HostPolicyResponseActionDetails;
configure_logging: HostPolicyResponseActionDetails;
configure_malware: HostPolicyResponseActionDetails;
connect_kernel: HostPolicyResponseActionDetails;
detect_file_open_events: HostPolicyResponseActionDetails;
detect_file_write_events: HostPolicyResponseActionDetails;
detect_image_load_events: HostPolicyResponseActionDetails;
detect_process_events: HostPolicyResponseActionDetails;
download_global_artifacts: HostPolicyResponseActionDetails;
load_config: HostPolicyResponseActionDetails;
load_malware_model: HostPolicyResponseActionDetails;
read_elasticsearch_config: HostPolicyResponseActionDetails;
read_events_config: HostPolicyResponseActionDetails;
read_kernel_config: HostPolicyResponseActionDetails;
read_logging_config: HostPolicyResponseActionDetails;
read_malware_config: HostPolicyResponseActionDetails;
// The list of possible Actions will change rapidly, so the below entry will allow
// them without us defining them here statically
[key: string]: HostPolicyResponseActionDetails;
}

interface HostPolicyResponseConfigurationStatus {
status: HostPolicyResponseActionStatus;
concerned_actions: Array<keyof HostPolicyResponseActions>;
}

/**
* Information about the applying of a policy to a given host
*/
export interface HostPolicyResponse {
'@timestamp': string;
elastic: {
agent: {
id: string;
};
};
ecs: {
version: string;
};
event: {
created: string;
kind: string;
};
agent: {
version: string;
id: string;
};
endpoint: {
artifacts: {};
policy: {
applied: {
version: string;
id: string;
status: HostPolicyResponseActionStatus;
response: {
configurations: {
malware: HostPolicyResponseConfigurationStatus;
events: HostPolicyResponseConfigurationStatus;
logging: HostPolicyResponseConfigurationStatus;
streaming: HostPolicyResponseConfigurationStatus;
};
actions: Partial<HostPolicyResponseActions>;
};
};
};
};
}

/**
* REST API response for retrieving a host's Policy Response status
*/
export interface GetHostPolicyResponse {
policy_response: HostPolicyResponse;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { ServerApiError } from '../../types';
import { HostResultList, HostInfo } from '../../../../../common/types';
import { HostResultList, HostInfo, GetHostPolicyResponse } from '../../../../../common/types';

interface ServerReturnedHostList {
type: 'serverReturnedHostList';
Expand All @@ -27,8 +27,14 @@ interface ServerFailedToReturnHostDetails {
payload: ServerApiError;
}

interface ServerReturnedHostPolicyResponse {
type: 'serverReturnedHostPolicyResponse';
payload: GetHostPolicyResponse;
}

export type HostAction =
| ServerReturnedHostList
| ServerFailedToReturnHostList
| ServerReturnedHostDetails
| ServerFailedToReturnHostDetails;
| ServerFailedToReturnHostDetails
| ServerReturnedHostPolicyResponse;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { HostResultList } from '../../../../../common/types';
import { isOnHostPage, hasSelectedHost, uiQueryParams, listData } from './selectors';
import { HostState } from '../../types';
import { ImmutableMiddlewareFactory } from '../../types';
import { HostPolicyResponse } from '../../../../../common/types';

export const hostMiddlewareFactory: ImmutableMiddlewareFactory<HostState> = coreStart => {
return ({ getState, dispatch }) => next => async action => {
Expand Down Expand Up @@ -69,6 +70,21 @@ export const hostMiddlewareFactory: ImmutableMiddlewareFactory<HostState> = core
type: 'serverReturnedHostDetails',
payload: response,
});
// FIXME: once we have the API implementation in place, we should call it parallel with the above api call and then dispatch this with the results of the second call
dispatch({
type: 'serverReturnedHostPolicyResponse',
payload: {
policy_response: ({
endpoint: {
policy: {
applied: {
status: 'success',
},
},
},
} as unknown) as HostPolicyResponse, // Temporary until we get API
},
});
} catch (error) {
dispatch({
type: 'serverFailedToReturnHostDetails',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const initialState = (): HostState => {
details: undefined,
detailsLoading: false,
detailsError: undefined,
policyResponse: undefined,
location: undefined,
};
};
Expand Down Expand Up @@ -63,6 +64,11 @@ export const hostListReducer: ImmutableReducer<HostState, AppAction> = (
detailsError: action.payload,
detailsLoading: false,
};
} else if (action.type === 'serverReturnedHostPolicyResponse') {
return {
...state,
policyResponse: action.payload.policy_response,
};
} else if (action.type === 'userChangedUrl') {
const newState: Immutable<HostState> = {
...state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,13 @@ export const showView: (state: HostState) => 'policy_response' | 'details' = cre
return searchParams.show === 'policy_response' ? 'policy_response' : 'details';
}
);

/**
* Returns the Policy Response overall status
*/
export const policyResponseStatus: (state: Immutable<HostState>) => string = createSelector(
state => state.policyResponse,
policyResponse => {
return (policyResponse && policyResponse?.endpoint?.policy?.applied?.status) || '';
}
);
3 changes: 3 additions & 0 deletions x-pack/plugins/endpoint/public/applications/endpoint/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
MalwareFields,
UIPolicyConfig,
PolicyData,
HostPolicyResponse,
} from '../../../common/types';
import { EndpointPluginStartDependencies } from '../../plugin';
import { AppAction } from './store/action';
Expand Down Expand Up @@ -107,6 +108,8 @@ export interface HostState {
detailsLoading: boolean;
/** api error from retrieving host details */
detailsError?: ServerApiError;
/** Holds the Policy Response for the Host currently being displayed in the details */
policyResponse?: HostPolicyResponse;
/** current location info */
location?: Immutable<EndpointAppLocation>;
}
Expand Down
Loading

0 comments on commit d77adb7

Please sign in to comment.