Skip to content

Commit

Permalink
[Endpoint] Add Endpoint Details route (#55746)
Browse files Browse the repository at this point in the history
* Add Endpoint Details route

* add Endpoint Details tests

* sacrifices to the Type gods

* update to latest endpoint schema

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
pzl and elasticmachine authored Jan 30, 2020
1 parent 2b53c74 commit 8398a1c
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 4 deletions.
78 changes: 78 additions & 0 deletions x-pack/plugins/endpoint/server/routes/endpoints.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,82 @@ describe('test endpoint route', () => {
expect(endpointResultList.request_page_index).toEqual(10);
expect(endpointResultList.request_page_size).toEqual(10);
});

describe('Endpoint Details route', () => {
it('should return 404 on no results', async () => {
const mockRequest = httpServerMock.createKibanaRequest({ params: { id: 'BADID' } });
mockScopedClient.callAsCurrentUser.mockImplementationOnce(() =>
Promise.resolve({
took: 3,
timed_out: false,
_shards: {
total: 1,
successful: 1,
skipped: 0,
failed: 0,
},
hits: {
total: {
value: 9,
relation: 'eq',
},
max_score: null,
hits: [],
},
})
);
[routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) =>
path.startsWith('/api/endpoint/endpoints')
)!;

await routeHandler(
({
core: {
elasticsearch: {
dataClient: mockScopedClient,
},
},
} as unknown) as RequestHandlerContext,
mockRequest,
mockResponse
);

expect(mockScopedClient.callAsCurrentUser).toBeCalled();
expect(routeConfig.options).toEqual({ authRequired: true });
expect(mockResponse.notFound).toBeCalled();
const message = mockResponse.notFound.mock.calls[0][0]?.body;
expect(message).toEqual('Endpoint Not Found');
});

it('should return a single endpoint', async () => {
const mockRequest = httpServerMock.createKibanaRequest({
params: { id: (data as any).hits.hits[0]._id },
});
const response: SearchResponse<EndpointMetadata> = (data as unknown) as SearchResponse<
EndpointMetadata
>;
mockScopedClient.callAsCurrentUser.mockImplementationOnce(() => Promise.resolve(response));
[routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) =>
path.startsWith('/api/endpoint/endpoints')
)!;

await routeHandler(
({
core: {
elasticsearch: {
dataClient: mockScopedClient,
},
},
} as unknown) as RequestHandlerContext,
mockRequest,
mockResponse
);

expect(mockScopedClient.callAsCurrentUser).toBeCalled();
expect(routeConfig.options).toEqual({ authRequired: true });
expect(mockResponse.ok).toBeCalled();
const result = mockResponse.ok.mock.calls[0][0]?.body as EndpointMetadata;
expect(result).toHaveProperty('endpoint');
});
});
});
32 changes: 31 additions & 1 deletion x-pack/plugins/endpoint/server/routes/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { IRouter } from 'kibana/server';
import { SearchResponse } from 'elasticsearch';
import { schema } from '@kbn/config-schema';

import { kibanaRequestToEndpointListQuery } from '../services/endpoint/endpoint_query_builders';
import {
kibanaRequestToEndpointListQuery,
kibanaRequestToEndpointFetchQuery,
} from '../services/endpoint/endpoint_query_builders';
import { EndpointMetadata, EndpointResultList } from '../../common/types';
import { EndpointAppContext } from '../types';

Expand Down Expand Up @@ -51,6 +54,33 @@ export function registerEndpointRoutes(router: IRouter, endpointAppContext: Endp
}
}
);

router.get(
{
path: '/api/endpoint/endpoints/{id}',
validate: {
params: schema.object({ id: schema.string() }),
},
options: { authRequired: true },
},
async (context, req, res) => {
try {
const query = kibanaRequestToEndpointFetchQuery(req, endpointAppContext);
const response = (await context.core.elasticsearch.dataClient.callAsCurrentUser(
'search',
query
)) as SearchResponse<EndpointMetadata>;

if (response.hits.hits.length === 0) {
return res.notFound({ body: 'Endpoint Not Found' });
}

return res.ok({ body: response.hits.hits[0]._source });
} catch (err) {
return res.internalError({ body: err });
}
}
);
}

function mapToEndpointResultList(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
*/
import { httpServerMock, loggingServiceMock } from '../../../../../../src/core/server/mocks';
import { EndpointConfigSchema } from '../../config';
import { kibanaRequestToEndpointListQuery } from './endpoint_query_builders';
import {
kibanaRequestToEndpointListQuery,
kibanaRequestToEndpointFetchQuery,
} from './endpoint_query_builders';

describe('test query builder', () => {
describe('test query builder request processing', () => {
describe('query builder', () => {
describe('EndpointListQuery', () => {
it('test default query params for all endpoints when no params or body is provided', async () => {
const mockRequest = httpServerMock.createKibanaRequest({
body: {},
Expand Down Expand Up @@ -51,4 +54,27 @@ describe('test query builder', () => {
} as Record<string, any>);
});
});

describe('EndpointFetchQuery', () => {
it('searches for the correct ID', () => {
const mockID = 'AABBCCDD-0011-2233-AA44-DEADBEEF8899';
const mockRequest = httpServerMock.createKibanaRequest({
params: {
id: mockID,
},
});
const query = kibanaRequestToEndpointFetchQuery(mockRequest, {
logFactory: loggingServiceMock.create(),
config: () => Promise.resolve(EndpointConfigSchema.validate({})),
});
expect(query).toEqual({
body: {
query: { match: { 'host.id.keyword': mockID } },
sort: [{ 'event.created': { order: 'desc' } }],
size: 1,
},
index: 'endpoint-agent*',
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,27 @@ async function getPagingProperties(
pageIndex: pagingProperties.page_index || config.endpointResultListDefaultFirstPageIndex,
};
}

export const kibanaRequestToEndpointFetchQuery = (
request: KibanaRequest<any, any, any>,
endpointAppContext: EndpointAppContext
) => {
return {
body: {
query: {
match: {
'host.id.keyword': request.params.id,
},
},
sort: [
{
'event.created': {
order: 'desc',
},
},
],
size: 1,
},
index: EndpointAppConstants.ENDPOINT_INDEX_NAME,
};
};

0 comments on commit 8398a1c

Please sign in to comment.