From f317c2585252a177eae85c1aa71957ef4da6af02 Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Wed, 13 Nov 2019 15:42:46 +0100 Subject: [PATCH] =?UTF-8?q?[APM]=20Use=20callWithInternalUser=20for=20agen?= =?UTF-8?q?t=20configuration=20endpoin=E2=80=A6=20(#50211)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [APM] Use callWithInternalUser for agent configuration endpoints Closes #50050. * Review feedback * Use internalClient for agent conf queries only --- x-pack/legacy/plugins/apm/index.ts | 2 +- .../plugins/apm/public/utils/testHelpers.tsx | 19 +++++++++++- .../__tests__/get_buckets.test.ts | 3 ++ .../apm/server/lib/helpers/es_client.ts | 29 +++++++++++++------ .../server/lib/helpers/setup_request.test.ts | 29 +++++++++++++++++-- .../apm/server/lib/helpers/setup_request.ts | 3 +- .../create_or_update_configuration.ts | 4 +-- .../delete_configuration.ts | 4 +-- .../get_existing_environments_for_service.ts | 4 +-- .../list_configurations.ts | 4 +-- .../mark_applied_by_agent.ts | 4 +-- .../agent_configuration/search.test.ts | 2 ++ .../settings/agent_configuration/search.ts | 6 ++-- .../lib/transaction_groups/fetcher.test.ts | 3 ++ .../lib/transactions/breakdown/index.test.ts | 5 ++++ .../charts/get_anomaly_data/index.test.ts | 1 + .../get_timeseries_data/fetcher.test.ts | 1 + .../server/routes/create_api/index.test.ts | 21 +++++++++++++- .../apm/server/routes/create_api/index.ts | 15 ++++------ .../routes/settings/agent_configuration.ts | 9 ++++++ .../plugins/apm/server/routes/typings.ts | 3 ++ 21 files changed, 135 insertions(+), 36 deletions(-) diff --git a/x-pack/legacy/plugins/apm/index.ts b/x-pack/legacy/plugins/apm/index.ts index fe8cc43d7f55dc..4655e5e6f92ea8 100644 --- a/x-pack/legacy/plugins/apm/index.ts +++ b/x-pack/legacy/plugins/apm/index.ts @@ -87,7 +87,7 @@ export const apm: LegacyPluginInitializer = kibana => { catalogue: ['apm'], privileges: { all: { - api: ['apm'], + api: ['apm', 'apm_write'], catalogue: ['apm'], savedObject: { all: [], diff --git a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx index a18882120fe757..a224df9e59e58f 100644 --- a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx +++ b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx @@ -97,6 +97,7 @@ interface MockSetup { start: number; end: number; client: any; + internalClient: any; config: { get: any; has: any; @@ -122,12 +123,21 @@ export async function inspectSearchParams( } }); + const internalClientSpy = jest.fn().mockReturnValueOnce({ + hits: { + total: 0 + } + }); + const mockSetup = { start: 1528113600000, end: 1528977600000, client: { search: clientSpy } as any, + internalClient: { + search: internalClientSpy + } as any, config: { get: () => 'myIndex' as any, has: () => true @@ -153,8 +163,15 @@ export async function inspectSearchParams( // we're only extracting the search params } + let params; + if (clientSpy.mock.calls.length) { + params = clientSpy.mock.calls[0][0]; + } else { + params = internalClientSpy.mock.calls[0][0]; + } + return { - params: clientSpy.mock.calls[0][0], + params, teardown: () => clientSpy.mockClear() }; } diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts index b7081c43465bf8..5bbd6be14a7082 100644 --- a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts @@ -31,6 +31,9 @@ describe('timeseriesFetcher', () => { client: { search: clientSpy } as any, + internalClient: { + search: clientSpy + } as any, config: { get: () => 'myIndex' as any, has: () => true diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts index ee41599454dd69..f38184fe460b1f 100644 --- a/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts +++ b/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts @@ -92,10 +92,23 @@ interface APMOptions { includeLegacyData: boolean; } -export function getESClient(req: Legacy.Request) { +interface ClientCreateOptions { + clientAsInternalUser?: boolean; +} + +export type ESClient = ReturnType; + +export function getESClient( + req: Legacy.Request, + { clientAsInternalUser = false }: ClientCreateOptions = {} +) { const cluster = req.server.plugins.elasticsearch.getCluster('data'); const query = req.query as Record; + const callMethod = clientAsInternalUser + ? cluster.callWithInternalUser.bind(cluster) + : cluster.callWithRequest.bind(cluster, req); + return { search: async < TDocument = unknown, @@ -121,20 +134,18 @@ export function getESClient(req: Legacy.Request) { console.log(JSON.stringify(nextParams.body, null, 4)); } - return (cluster.callWithRequest( - req, - 'search', - nextParams - ) as unknown) as Promise>; + return (callMethod('search', nextParams) as unknown) as Promise< + ESSearchResponse + >; }, index: (params: APMIndexDocumentParams) => { - return cluster.callWithRequest(req, 'index', params); + return callMethod('index', params); }, delete: (params: IndicesDeleteParams) => { - return cluster.callWithRequest(req, 'delete', params); + return callMethod('delete', params); }, indicesCreate: (params: IndicesCreateParams) => { - return cluster.callWithRequest(req, 'indices.create', params); + return callMethod('indices.create', params); } }; } diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts index 57de438be7f2ad..6ebf7a896591ff 100644 --- a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts @@ -21,6 +21,7 @@ jest.mock('../settings/apm_indices/get_apm_indices', () => ({ function getMockRequest() { const callWithRequestSpy = jest.fn(); + const callWithInternalUserSpy = jest.fn(); const mockRequest = ({ params: {}, query: {}, @@ -28,14 +29,17 @@ function getMockRequest() { config: () => ({ get: () => 'apm-*' }), plugins: { elasticsearch: { - getCluster: () => ({ callWithRequest: callWithRequestSpy }) + getCluster: () => ({ + callWithRequest: callWithRequestSpy, + callWithInternalUser: callWithInternalUserSpy + }) } } }, getUiSettingsService: () => ({ get: async () => false }) } as any) as Legacy.Request; - return { callWithRequestSpy, mockRequest }; + return { callWithRequestSpy, callWithInternalUserSpy, mockRequest }; } describe('setupRequest', () => { @@ -57,6 +61,27 @@ describe('setupRequest', () => { }); }); + it('should call callWithInternalUser with default args', async () => { + const { mockRequest, callWithInternalUserSpy } = getMockRequest(); + const { internalClient } = await setupRequest(mockRequest); + await internalClient.search({ + index: 'apm-*', + body: { foo: 'bar' } + } as any); + expect(callWithInternalUserSpy).toHaveBeenCalledWith('search', { + index: 'apm-*', + body: { + foo: 'bar', + query: { + bool: { + filter: [{ range: { 'observer.version_major': { gte: 7 } } }] + } + } + }, + ignore_throttled: true + }); + }); + describe('observer.version_major filter', () => { describe('if index is apm-*', () => { it('should merge `observer.version_major` filter with existing boolean filters', async () => { diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.ts index 3ec519d5e71b57..850de4939d5997 100644 --- a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.ts +++ b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.ts @@ -41,7 +41,8 @@ export async function setupRequest(req: Legacy.Request) { start: moment.utc(query.start).valueOf(), end: moment.utc(query.end).valueOf(), uiFiltersES, - client: getESClient(req), + client: getESClient(req, { clientAsInternalUser: false }), + internalClient: getESClient(req, { clientAsInternalUser: true }), config, indices }; diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts index 25a4f5141498f4..23faa4b74cf8fb 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts @@ -21,7 +21,7 @@ export async function createOrUpdateConfiguration({ >; setup: Setup; }) { - const { client, indices } = setup; + const { internalClient, indices } = setup; const params: APMIndexDocumentParams = { refresh: true, @@ -44,5 +44,5 @@ export async function createOrUpdateConfiguration({ params.id = configurationId; } - return client.index(params); + return internalClient.index(params); } diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts index 896363c054ba78..ed20a58b271e10 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts @@ -13,7 +13,7 @@ export async function deleteConfiguration({ configurationId: string; setup: Setup; }) { - const { client, indices } = setup; + const { internalClient, indices } = setup; const params = { refresh: 'wait_for', @@ -21,5 +21,5 @@ export async function deleteConfiguration({ id: configurationId }; - return client.delete(params); + return internalClient.delete(params); } diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts index d5aa389cea3357..52efc2b50305b9 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts @@ -19,7 +19,7 @@ export async function getExistingEnvironmentsForService({ serviceName: string | undefined; setup: Setup; }) { - const { client, indices } = setup; + const { internalClient, indices } = setup; const bool = serviceName ? { filter: [{ term: { [SERVICE_NAME]: serviceName } }] } @@ -42,7 +42,7 @@ export async function getExistingEnvironmentsForService({ } }; - const resp = await client.search(params); + const resp = await internalClient.search(params); const buckets = idx(resp.aggregations, _ => _.environments.buckets) || []; return buckets.map(bucket => bucket.key as string); } diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts index 283f30b51441d3..dd4d019ef7263b 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts @@ -12,13 +12,13 @@ export type AgentConfigurationListAPIResponse = PromiseReturnType< typeof listConfigurations >; export async function listConfigurations({ setup }: { setup: Setup }) { - const { client, indices } = setup; + const { internalClient, indices } = setup; const params = { index: indices['apm_oss.apmAgentConfigurationIndex'] }; - const resp = await client.search(params); + const resp = await internalClient.search(params); return resp.hits.hits.map(item => ({ id: item._id, ...item._source diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts index e5349edb67f308..b7b9c21172140a 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts @@ -16,7 +16,7 @@ export async function markAppliedByAgent({ body: AgentConfiguration; setup: Setup; }) { - const { client, indices } = setup; + const { internalClient, indices } = setup; const params = { index: indices['apm_oss.apmAgentConfigurationIndex'], @@ -27,5 +27,5 @@ export async function markAppliedByAgent({ } }; - return client.index(params); + return internalClient.index(params); } diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.test.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.test.ts index 400bd0207771af..dcf7329b229d85 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.test.ts @@ -16,6 +16,7 @@ describe('search configurations', () => { setup: ({ config: { get: () => '' }, client: { search: async () => searchMocks }, + internalClient: { search: async () => searchMocks }, indices: { apm_oss: { sourcemapIndices: 'myIndex', @@ -41,6 +42,7 @@ describe('search configurations', () => { setup: ({ config: { get: () => '' }, client: { search: async () => searchMocks }, + internalClient: { search: async () => searchMocks }, indices: { apm_oss: { sourcemapIndices: 'myIndex', diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts index 35d76d745cf4f1..969bbc542f8a6e 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts @@ -20,7 +20,7 @@ export async function searchConfigurations({ environment?: string; setup: Setup; }) { - const { client, indices } = setup; + const { internalClient, indices } = setup; // sorting order // 1. exact match: service.name AND service.environment (eg. opbeans-node / production) @@ -49,7 +49,9 @@ export async function searchConfigurations({ } }; - const resp = await client.search(params); + const resp = await internalClient.search( + params + ); const { hits } = resp.hits; const exactMatch = hits.find( diff --git a/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.test.ts b/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.test.ts index 99553690359cf5..ca10183bb259e4 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.test.ts @@ -13,6 +13,9 @@ function getSetup() { client: { search: jest.fn() } as any, + internalClient: { + search: jest.fn() + } as any, config: { get: jest.fn((key: string) => { switch (key) { diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts index 67816d67a29a2a..2648851789c662 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts @@ -30,6 +30,7 @@ describe('getTransactionBreakdown', () => { start: 0, end: 500000, client: { search: clientSpy } as any, + internalClient: { search: clientSpy } as any, config: { get: () => 'myIndex' as any, has: () => true @@ -54,6 +55,7 @@ describe('getTransactionBreakdown', () => { start: 0, end: 500000, client: { search: clientSpy } as any, + internalClient: { search: clientSpy } as any, config: { get: () => 'myIndex' as any, has: () => true @@ -95,6 +97,7 @@ describe('getTransactionBreakdown', () => { start: 0, end: 500000, client: { search: clientSpy } as any, + internalClient: { search: clientSpy } as any, config: { get: () => 'myIndex' as any, has: () => true @@ -135,6 +138,7 @@ describe('getTransactionBreakdown', () => { start: 0, end: 500000, client: { search: clientSpy } as any, + internalClient: { search: clientSpy } as any, config: { get: () => 'myIndex' as any, has: () => true @@ -159,6 +163,7 @@ describe('getTransactionBreakdown', () => { start: 0, end: 500000, client: { search: clientSpy } as any, + internalClient: { search: clientSpy } as any, config: { get: () => 'myIndex' as any, has: () => true diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts index cddc66e52cf701..3b9e80c901fe92 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts @@ -26,6 +26,7 @@ describe('getAnomalySeries', () => { start: 0, end: 500000, client: { search: clientSpy } as any, + internalClient: { search: clientSpy } as any, config: { get: () => 'myIndex' as any, has: () => true diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts index 5056a100de3ce6..0345b0815679f6 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts @@ -21,6 +21,7 @@ describe('timeseriesFetcher', () => { start: 1528113600000, end: 1528977600000, client: { search: clientSpy } as any, + internalClient: { search: clientSpy } as any, config: { get: () => 'myIndex' as any, has: () => true diff --git a/x-pack/legacy/plugins/apm/server/routes/create_api/index.test.ts b/x-pack/legacy/plugins/apm/server/routes/create_api/index.test.ts index 98eae3196eaacb..18fe547a34cf01 100644 --- a/x-pack/legacy/plugins/apm/server/routes/create_api/index.test.ts +++ b/x-pack/legacy/plugins/apm/server/routes/create_api/index.test.ts @@ -38,9 +38,17 @@ describe('createApi', () => { }, handler: async () => null })) + .add(() => ({ + path: '/baz', + method: 'PUT', + options: { + tags: ['access:apm', 'access:apm_write'] + }, + handler: async () => null + })) .init(coreMock, legacySetupMock); - expect(legacySetupMock.server.route).toHaveBeenCalledTimes(2); + expect(legacySetupMock.server.route).toHaveBeenCalledTimes(3); const firstRoute = legacySetupMock.server.route.mock.calls[0][0]; @@ -63,6 +71,17 @@ describe('createApi', () => { path: '/bar', handler: expect.any(Function) }); + + const thirdRoute = legacySetupMock.server.route.mock.calls[2][0]; + + expect(thirdRoute).toEqual({ + method: 'PUT', + options: { + tags: ['access:apm', 'access:apm_write'] + }, + path: '/baz', + handler: expect.any(Function) + }); }); describe('when validating', () => { diff --git a/x-pack/legacy/plugins/apm/server/routes/create_api/index.ts b/x-pack/legacy/plugins/apm/server/routes/create_api/index.ts index eae4fd4988debd..2ce27fbc5e5e49 100644 --- a/x-pack/legacy/plugins/apm/server/routes/create_api/index.ts +++ b/x-pack/legacy/plugins/apm/server/routes/create_api/index.ts @@ -33,12 +33,11 @@ export function createApi() { init(core: CoreSetup, __LEGACY: LegacySetup) { const { server } = __LEGACY; factoryFns.forEach(fn => { - const { params = {}, ...route } = fn(core, __LEGACY) as Route< - string, - HttpMethod, - Params, - any - >; + const { + params = {}, + options = { tags: ['access:apm'] }, + ...route + } = fn(core, __LEGACY) as Route; const bodyRt = params.body; const fallbackBodyRt = bodyRt || t.null; @@ -55,9 +54,7 @@ export function createApi() { server.route( merge( { - options: { - tags: ['access:apm'] - }, + options, method: 'GET' }, route, diff --git a/x-pack/legacy/plugins/apm/server/routes/settings/agent_configuration.ts b/x-pack/legacy/plugins/apm/server/routes/settings/agent_configuration.ts index d25ad949d6ddef..2867cef28d952b 100644 --- a/x-pack/legacy/plugins/apm/server/routes/settings/agent_configuration.ts +++ b/x-pack/legacy/plugins/apm/server/routes/settings/agent_configuration.ts @@ -31,6 +31,9 @@ export const agentConfigurationRoute = createRoute(core => ({ export const deleteAgentConfigurationRoute = createRoute(() => ({ method: 'DELETE', path: '/api/apm/settings/agent-configuration/{configurationId}', + options: { + tags: ['access:apm', 'access:apm_write'] + }, params: { path: t.type({ configurationId: t.string @@ -108,6 +111,9 @@ export const createAgentConfigurationRoute = createRoute(() => ({ params: { body: agentPayloadRt }, + options: { + tags: ['access:apm', 'access:apm_write'] + }, handler: async (req, { body }) => { const setup = await setupRequest(req); return await createOrUpdateConfiguration({ configuration: body, setup }); @@ -117,6 +123,9 @@ export const createAgentConfigurationRoute = createRoute(() => ({ export const updateAgentConfigurationRoute = createRoute(() => ({ method: 'PUT', path: '/api/apm/settings/agent-configuration/{configurationId}', + options: { + tags: ['access:apm', 'access:apm_write'] + }, params: { path: t.type({ configurationId: t.string diff --git a/x-pack/legacy/plugins/apm/server/routes/typings.ts b/x-pack/legacy/plugins/apm/server/routes/typings.ts index 8ba8c067fb961a..cf1a6cf7694523 100644 --- a/x-pack/legacy/plugins/apm/server/routes/typings.ts +++ b/x-pack/legacy/plugins/apm/server/routes/typings.ts @@ -34,6 +34,9 @@ export interface Route< path: TPath; method?: TMethod; params?: TParams; + options?: { + tags: Array<'access:apm' | 'access:apm_write'>; + }; handler: ( req: Request, params: DecodeParams,