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

[7.x] [Endpoint]EMT-451: add ability to filter endpoint metadata based on presence of unenrolled events (#69708) #69971

Merged
merged 1 commit into from
Jun 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
export const eventsIndexPattern = 'logs-endpoint.events.*';
export const alertsIndexPattern = 'logs-endpoint.alerts-*';
export const metadataIndexPattern = 'metrics-endpoint.metadata-*';
export const metadataMirrorIndexPattern = 'metrics-endpoint.metadata_mirror-*';
export const policyIndexPattern = 'metrics-endpoint.policy-*';
export const telemetryIndexPattern = 'metrics-endpoint.telemetry-*';
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
HostPolicyResponse,
HostPolicyResponseActionStatus,
PolicyData,
EndpointStatus,
} from './types';
import { factory as policyFactory } from './models/policy_config';

Expand Down Expand Up @@ -209,6 +210,7 @@ interface HostInfo {
};
host: Host;
Endpoint: {
status: EndpointStatus;
policy: {
applied: {
id: string;
Expand Down Expand Up @@ -305,7 +307,7 @@ export class EndpointDocGenerator {
* Creates new random policy id for the host to simulate new policy application
*/
public updatePolicyId() {
this.commonInfo.Endpoint.policy.applied = this.randomChoice(APPLIED_POLICIES);
this.commonInfo.Endpoint.policy.applied.id = this.randomChoice(APPLIED_POLICIES).id;
this.commonInfo.Endpoint.policy.applied.status = this.randomChoice([
HostPolicyResponseActionStatus.success,
HostPolicyResponseActionStatus.failure,
Expand Down Expand Up @@ -333,6 +335,7 @@ export class EndpointDocGenerator {
os: this.randomChoice(OS),
},
Endpoint: {
status: EndpointStatus.enrolled,
policy: {
applied: this.randomChoice(APPLIED_POLICIES),
},
Expand Down
19 changes: 18 additions & 1 deletion x-pack/plugins/security_solution/common/endpoint/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,23 @@ export interface AlertEvent {
}

/**
* The status of the host
* The status of the Endpoint Agent as reported by the Agent or the
* Security Solution app using events from Fleet.
*/
export enum EndpointStatus {
/**
* Agent is enrolled with Fleet
*/
enrolled = 'enrolled',

/**
* Agent is unenrrolled from Fleet
*/
unenrolled = 'unenrolled',
}

/**
* The status of the host, which is mapped to the Elastic Agent status in Fleet
*/
export enum HostStatus {
/**
Expand Down Expand Up @@ -386,6 +402,7 @@ export type HostMetadata = Immutable<{
};
};
Endpoint: {
status: EndpointStatus;
policy: {
applied: {
id: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { IRouter, Logger, RequestHandlerContext } from 'kibana/server';
import { SearchResponse } from 'elasticsearch';
import { schema } from '@kbn/config-schema';

import Boom from 'boom';
import { metadataIndexPattern } from '../../../../common/endpoint/constants';
import { getESQueryHostMetadataByID, kibanaRequestToMetadataListESQuery } from './query_builders';
import {
Expand All @@ -18,6 +19,7 @@ import {
} from '../../../../common/endpoint/types';
import { EndpointAppContext } from '../../types';
import { AgentStatus } from '../../../../../ingest_manager/common/types/models';
import { findAllUnenrolledHostIds, findUnenrolledHostByHostId, HostId } from './support/unenroll';

interface HitSource {
_source: HostMetadata;
Expand Down Expand Up @@ -68,10 +70,17 @@ export function registerEndpointRoutes(router: IRouter, endpointAppContext: Endp
},
async (context, req, res) => {
try {
const unenrolledHostIds = await findAllUnenrolledHostIds(
context.core.elasticsearch.legacy.client
);

const queryParams = await kibanaRequestToMetadataListESQuery(
req,
endpointAppContext,
metadataIndexPattern
metadataIndexPattern,
{
unenrolledHostIds: unenrolledHostIds.map((host: HostId) => host.host.id),
}
);
const response = (await context.core.elasticsearch.legacy.client.callAsCurrentUser(
'search',
Expand Down Expand Up @@ -113,6 +122,12 @@ export function registerEndpointRoutes(router: IRouter, endpointAppContext: Endp
return res.notFound({ body: 'Endpoint Not Found' });
} catch (err) {
logger.warn(JSON.stringify(err, null, 2));
if (err.isBoom) {
return res.customError({
statusCode: err.output.statusCode,
body: { message: err.message },
});
}
return res.internalError({ body: err });
}
}
Expand All @@ -123,6 +138,13 @@ export async function getHostData(
metadataRequestContext: MetadataRequestContext,
id: string
): Promise<HostInfo | undefined> {
const unenrolledHostId = await findUnenrolledHostByHostId(
metadataRequestContext.requestHandlerContext.core.elasticsearch.legacy.client,
id
);
if (unenrolledHostId) {
throw Boom.badRequest('the requested endpoint is unenrolled');
}
const query = getESQueryHostMetadataByID(id, metadataIndexPattern);
const response = (await metadataRequestContext.requestHandlerContext.core.elasticsearch.legacy.client.callAsCurrentUser(
'search',
Expand Down
Loading