diff --git a/x-pack/legacy/plugins/apm/index.ts b/x-pack/legacy/plugins/apm/index.ts index 4d3d2b210bbae6..7eb87a6e733765 100644 --- a/x-pack/legacy/plugins/apm/index.ts +++ b/x-pack/legacy/plugins/apm/index.ts @@ -91,7 +91,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 73b81bfed4794c..bb27860dc82576 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; @@ -113,12 +114,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 @@ -135,8 +145,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 0b8cd8ae8703f8..f20dbc3ef361ec 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 03cfa7e0c8a83d..dc65e82b9f5452 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 @@ -84,10 +84,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 StringMap; + const callMethod = clientAsInternalUser + ? cluster.callWithInternalUser.bind(cluster) + : cluster.callWithRequest.bind(cluster, req); + return { search: async ( params: U, @@ -110,22 +123,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< AggregationSearchResponseWithTotalHitsAsObject >; }, index: (params: IndexDocumentParams) => { - 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 cfc33b4fad7ea3..c4fc07d7cc842e 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 @@ -10,6 +10,7 @@ import { uiSettingsServiceMock } from 'src/core/server/mocks'; function getMockRequest() { const callWithRequestSpy = jest.fn(); + const callWithInternalUserSpy = jest.fn(); const mockRequest = ({ params: {}, query: {}, @@ -17,14 +18,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', () => { @@ -46,6 +50,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 4054537e04b40f..0ddd9df40995f7 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 @@ -36,7 +36,8 @@ export async function setupRequest(req: Legacy.Request) { start: moment.utc(query.start).valueOf(), end: moment.utc(query.end).valueOf(), uiFiltersES: await decodeUiFilters(server, query.uiFilters), - client: getESClient(req), + client: getESClient(req, { clientAsInternalUser: false }), + internalClient: getESClient(req, { clientAsInternalUser: true }), config }; } 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 6450040098cd40..36bf069b921bbc 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, config } = setup; + const { internalClient, config } = setup; const params: IndexDocumentParams = { type: '_doc', @@ -45,5 +45,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 82b192125a5cff..ccec6a3a6d804a 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, config } = setup; + const { internalClient, config } = 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 120cc62cc3bc99..4811b396392774 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, config } = setup; + const { internalClient, config } = 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); } 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 9edceb86dda8db..6a0837223a68eb 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, config } = setup; + const { internalClient, config } = setup; const params = { index: config.get('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 ea2b15e6985d5a..54ebd908f32054 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, config } = setup; + const { internalClient, config } = setup; const params = { type: '_doc', @@ -28,5 +28,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 e8db37891e7ae5..c05e9b79c2c021 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 @@ -15,7 +15,8 @@ describe('search configurations', () => { environment: 'production', setup: ({ config: { get: () => '' }, - client: { search: async () => searchMocks } + client: { search: async () => searchMocks }, + internalClient: { search: async () => searchMocks } } as unknown) as Setup }); @@ -29,7 +30,8 @@ describe('search configurations', () => { environment: 'production', setup: ({ config: { get: () => '' }, - client: { search: async () => searchMocks } + client: { search: async () => searchMocks }, + internalClient: { search: async () => searchMocks } } as unknown) as Setup }); 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 664bcb9325472e..0522f9d971dfec 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 @@ -21,7 +21,7 @@ export async function searchConfigurations({ environment?: string; setup: Setup; }) { - const { client, config } = setup; + const { internalClient, config } = setup; // sorting order // 1. exact match: service.name AND service.environment (eg. opbeans-node / production) @@ -50,7 +50,7 @@ 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 fc7b1b4127892f..c5aff0a17a5c0a 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 e707ce3eafe18a..4e8bf583e95381 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 @@ -20,6 +20,7 @@ describe('getTransactionBreakdown', () => { start: 0, end: 500000, client: { search: clientSpy } as any, + internalClient: { search: clientSpy } as any, config: { get: () => 'myIndex' as any, has: () => true @@ -43,6 +44,7 @@ describe('getTransactionBreakdown', () => { start: 0, end: 500000, client: { search: clientSpy } as any, + internalClient: { search: clientSpy } as any, config: { get: () => 'myIndex' as any, has: () => true @@ -83,6 +85,7 @@ describe('getTransactionBreakdown', () => { start: 0, end: 500000, client: { search: clientSpy } as any, + internalClient: { search: clientSpy } as any, config: { get: () => 'myIndex' as any, has: () => true @@ -122,6 +125,7 @@ describe('getTransactionBreakdown', () => { start: 0, end: 500000, client: { search: clientSpy } as any, + internalClient: { search: clientSpy } as any, config: { get: () => 'myIndex' as any, has: () => true @@ -145,6 +149,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 07f1d96618198b..088134272ddb93 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 dc568d653a5eef..3de9bdf6364acf 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 b0461f5cb3b68d..ca03318d1816dc 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 @@ -36,9 +36,17 @@ describe('createApi', () => { }, handler: async () => null })) + .add(() => ({ + path: '/baz', + method: 'PUT', + options: { + tags: ['access:apm', 'access:apm_write'] + }, + handler: async () => null + })) .init(coreMock); - expect(coreMock.http.server.route).toHaveBeenCalledTimes(2); + expect(coreMock.http.server.route).toHaveBeenCalledTimes(3); const firstRoute = coreMock.http.server.route.mock.calls[0][0]; @@ -61,6 +69,17 @@ describe('createApi', () => { path: '/bar', handler: expect.any(Function) }); + + const thirdRoute = coreMock.http.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 f969e4d6024ca5..c9f5dc0752726f 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 @@ -32,12 +32,11 @@ export function createApi() { init(core: InternalCoreSetup) { const { server } = core.http; factoryFns.forEach(fn => { - const { params = {}, ...route } = fn(core) as Route< - string, - HttpMethod, - Params, - any - >; + const { + params = {}, + options = { tags: ['access:apm'] }, + ...route + } = fn(core) as Route; const bodyRt = params.body; const fallbackBodyRt = bodyRt || t.null; @@ -54,9 +53,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.ts b/x-pack/legacy/plugins/apm/server/routes/settings.ts index 65ef5df78f3e12..ddb7f7e59ba02d 100644 --- a/x-pack/legacy/plugins/apm/server/routes/settings.ts +++ b/x-pack/legacy/plugins/apm/server/routes/settings.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 a0ddffe044c151..77c1cc88c6d99c 100644 --- a/x-pack/legacy/plugins/apm/server/routes/typings.ts +++ b/x-pack/legacy/plugins/apm/server/routes/typings.ts @@ -33,6 +33,9 @@ export interface Route< path: TPath; method?: TMethod; params?: TParams; + options?: { + tags: Array<'access:apm' | 'access:apm_write'>; + }; handler: ( req: Request, params: DecodeParams,