[APM] Update deprecated access tags to the new security configuration in routes (#204058)

## Summary

Closes https://github.com/elastic/kibana/issues/203792

This PR replaces the deprecated `access` tags with the new `security`
configuration.

All instances of `options: {tags: ['access:<privilege>']}` are now
updated to `security: {authz: {requiredPrivileges: [<privilege>]}}`.

These are the access tags currently used in APM that have been migrated:
- `access:apm`  
- `access:apm_write`  
- `access:apm_settings_write`  
- `access:ml:canGetJobs`  
- `access:ml:canCreateJob`  
- `access:ml:canCloseJob`  
- `access:ai_assistant`
This commit is contained in:
Irene Blanco 2024-12-13 16:43:04 +01:00 committed by GitHub
parent 0cd82ae09a
commit a4cf54c5d5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 291 additions and 271 deletions

View file

@ -19,7 +19,7 @@ import {
const agentExplorerRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/get_agents_per_service',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.type({
query: t.intersection([
environmentRt,
@ -62,7 +62,7 @@ const agentExplorerRoute = createApmServerRoute({
const latestAgentVersionsRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/get_latest_agent_versions',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
async handler(resources): Promise<AgentLatestVersionsResponse> {
const { logger, config } = resources;
@ -72,7 +72,7 @@ const latestAgentVersionsRoute = createApmServerRoute({
const agentExplorerInstanceRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/services/{serviceName}/agent_instances',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.type({
path: t.type({ serviceName: t.string }),
query: t.intersection([environmentRt, kueryRt, rangeRt, probabilityRt]),

View file

@ -17,7 +17,7 @@ import { privilegesTypeRt } from '../../../common/privilege_type';
const agentKeysRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/agent_keys',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<AgentKeysResponse> => {
const { context } = resources;
@ -31,8 +31,7 @@ const agentKeysRoute = createApmServerRoute({
const agentKeysPrivilegesRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/agent_keys/privileges',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<AgentKeysPrivilegesResponse> => {
const {
plugins: { security },
@ -55,7 +54,11 @@ const agentKeysPrivilegesRoute = createApmServerRoute({
const invalidateAgentKeyRoute = createApmServerRoute({
endpoint: 'POST /internal/apm/api_key/invalidate',
options: { tags: ['access:apm', 'access:apm_settings_write'] },
security: {
authz: {
requiredPrivileges: ['apm', 'apm_settings_write'],
},
},
params: t.type({
body: t.type({ id: t.string }),
}),
@ -91,7 +94,12 @@ const invalidateAgentKeyRoute = createApmServerRoute({
const createAgentKeyRoute = createApmServerRoute({
endpoint: 'POST /api/apm/agent_keys 2023-10-31',
options: { tags: ['access:apm', 'access:apm_settings_write', 'oas-tag:APM agent keys'] },
options: { tags: ['oas-tag:APM agent keys'] },
security: {
authz: {
requiredPrivileges: ['apm', 'apm_settings_write'],
},
},
params: t.type({
body: t.type({
name: t.string,

View file

@ -61,7 +61,7 @@ export type AlertParams = t.TypeOf<typeof alertParamsRt>;
const transactionErrorRateChartPreview = createApmServerRoute({
endpoint: 'GET /internal/apm/rule_types/transaction_error_rate/chart_preview',
params: t.type({ query: alertParamsRt }),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -84,7 +84,7 @@ const transactionErrorRateChartPreview = createApmServerRoute({
const transactionErrorCountChartPreview = createApmServerRoute({
endpoint: 'GET /internal/apm/rule_types/error_count/chart_preview',
params: t.type({ query: alertParamsRt }),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -107,7 +107,7 @@ const transactionErrorCountChartPreview = createApmServerRoute({
const transactionDurationChartPreview = createApmServerRoute({
endpoint: 'GET /internal/apm/rule_types/transaction_duration/chart_preview',
params: t.type({ query: alertParamsRt }),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{

View file

@ -69,7 +69,13 @@ const getRegisterRouteDependencies = () => {
const initApi = (
routes: Array<
ServerRoute<any, t.Any | undefined, APMRouteHandlerResources, any, APMRouteCreateOptions>
ServerRoute<
any,
t.Any | undefined,
APMRouteHandlerResources,
any,
APMRouteCreateOptions | undefined
>
>
) => {
const { mocks, dependencies } = getRegisterRouteDependencies();
@ -134,7 +140,7 @@ describe('createApi', () => {
} = initApi([
{
endpoint: 'GET /foo',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async () => ({}),
},
{
@ -142,28 +148,22 @@ describe('createApi', () => {
params: t.type({
body: t.string,
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async () => ({}),
},
{
endpoint: 'PUT /baz',
options: {
tags: ['access:apm', 'access:apm_write'],
},
security: { authz: { requiredPrivileges: ['apm', 'apm_write'] } },
handler: async () => ({}),
},
{
endpoint: 'GET /qux',
options: {
tags: ['access:apm', 'access:apm_write'],
},
security: { authz: { requiredPrivileges: ['apm', 'apm_write'] } },
handler: async () => ({}),
},
{
endpoint: 'GET /fez',
options: {
tags: ['access:apm', 'access:apm_settings_write'],
},
security: { authz: { requiredPrivileges: ['apm', 'apm_settings_write'] } },
handler: async () => ({}),
},
]);
@ -175,41 +175,36 @@ describe('createApi', () => {
expect(put).toHaveBeenCalledTimes(1);
expect(get.mock.calls[0][0]).toEqual({
options: {
tags: ['access:apm'],
},
options: {},
security: { authz: { requiredPrivileges: ['apm'] } },
path: '/foo',
validate: expect.anything(),
});
expect(get.mock.calls[1][0]).toEqual({
options: {
tags: ['access:apm', 'access:apm_write'],
},
options: {},
security: { authz: { requiredPrivileges: ['apm', 'apm_write'] } },
path: '/qux',
validate: expect.anything(),
});
expect(get.mock.calls[2][0]).toEqual({
options: {
tags: ['access:apm', 'access:apm_settings_write'],
},
options: {},
security: { authz: { requiredPrivileges: ['apm', 'apm_settings_write'] } },
path: '/fez',
validate: expect.anything(),
});
expect(post.mock.calls[0][0]).toEqual({
options: {
tags: ['access:apm'],
},
options: {},
security: { authz: { requiredPrivileges: ['apm'] } },
path: '/bar',
validate: expect.anything(),
});
expect(put.mock.calls[0][0]).toEqual({
options: {
tags: ['access:apm', 'access:apm_write'],
},
options: {},
security: { authz: { requiredPrivileges: ['apm', 'apm_write'] } },
path: '/baz',
validate: expect.anything(),
});

View file

@ -19,8 +19,10 @@ import { getApmTimeseries, getApmTimeseriesRt, type ApmTimeseries } from './get_
const getApmTimeSeriesRoute = createApmServerRoute({
endpoint: 'POST /internal/apm/assistant/get_apm_timeseries',
options: {
tags: ['access:apm', 'access:ai_assistant'],
security: {
authz: {
requiredPrivileges: ['apm', 'ai_assistant'],
},
},
params: t.type({
body: getApmTimeseriesRt,
@ -51,9 +53,7 @@ const getDownstreamDependenciesRoute = createApmServerRoute({
params: t.type({
query: downstreamDependenciesRouteRt,
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ content: APMDownstreamDependency[] }> => {
const {
params,

View file

@ -51,7 +51,7 @@ const fieldCandidatesTransactionsRoute = createApmServerRoute({
rangeRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<DurationFieldCandidatesResponse> => {
const { context } = resources;
const { license } = await context.licensing;
@ -104,7 +104,7 @@ const fieldValueStatsTransactionsRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<TopValuesStats> => {
const { context } = resources;
const { license } = await context.licensing;
@ -172,7 +172,7 @@ const fieldValuePairsTransactionsRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<FieldValuePairsResponse> => {
const { context } = resources;
const { license } = await context.licensing;
@ -240,7 +240,7 @@ const significantCorrelationsTransactionsRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<SignificantCorrelationsResponse> => {
const apmEventClient = await getApmEventClient(resources);
const {
@ -299,7 +299,7 @@ const pValuesTransactionsRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<PValuesResponse> => {
const apmEventClient = await getApmEventClient(resources);

View file

@ -33,7 +33,11 @@ const serviceDashboardSaveRoute = createApmServerRoute({
serviceEnvironmentFilterEnabled: t.boolean,
}),
}),
options: { tags: ['access:apm', 'access:apm_write'] },
security: {
authz: {
requiredPrivileges: ['apm', 'apm_write'],
},
},
handler: async (resources): Promise<SavedApmCustomDashboard> => {
const { context, params } = resources;
const { customDashboardId } = params.query;
@ -62,9 +66,7 @@ const serviceDashboardsRoute = createApmServerRoute({
}),
]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ serviceDashboards: SavedApmCustomDashboard[] }> => {
const { context, params, request } = resources;
const coreContext = await context.core;
@ -116,7 +118,11 @@ const serviceDashboardDeleteRoute = createApmServerRoute({
customDashboardId: t.string,
}),
}),
options: { tags: ['access:apm', 'access:apm_write'] },
security: {
authz: {
requiredPrivileges: ['apm', 'apm_write'],
},
},
handler: async (resources): Promise<void> => {
const { context, params } = resources;
const { customDashboardId } = params.query;

View file

@ -13,7 +13,7 @@ import { getApmEventClient } from '../../lib/helpers/get_apm_event_client';
const staticDataViewRoute = createApmServerRoute({
endpoint: 'POST /internal/apm/data_view/static',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): CreateDataViewResponse => {
const { context, plugins, request, logger } = resources;
const apmEventClient = await getApmEventClient(resources);
@ -49,7 +49,7 @@ const staticDataViewRoute = createApmServerRoute({
const dataViewTitleRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/data_view/index_pattern',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async ({ getApmIndices }): Promise<{ apmDataViewIndexPattern: string }> => {
const apmIndicies = await getApmIndices();
const apmDataViewIndexPattern = getApmDataViewIndexPattern(apmIndicies);

View file

@ -14,8 +14,10 @@ import {
} from '../../../common/apm_saved_object_constants';
export const debugTelemetryRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/debug-telemetry',
options: {
tags: ['access:apm', 'access:apm_write'],
security: {
authz: {
requiredPrivileges: ['apm', 'apm_write'],
},
},
handler: async (resources): Promise<APMTelemetry> => {
const { plugins, context } = resources;

View file

@ -47,9 +47,7 @@ const topDependenciesRoute = createApmServerRoute({
query: offsetRt,
}),
]),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<TopDependenciesResponse> => {
const {
request,
@ -89,9 +87,7 @@ const upstreamServicesForDependencyRoute = createApmServerRoute({
query: t.intersection([environmentRt, offsetRt, kueryRt]),
}),
]),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<UpstreamServicesForDependencyResponse> => {
const {
request,
@ -126,9 +122,7 @@ const dependencyMetadataRoute = createApmServerRoute({
params: t.type({
query: t.intersection([t.type({ dependencyName: t.string }), rangeRt]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -165,9 +159,7 @@ const dependencyLatencyChartsRoute = createApmServerRoute({
offsetRt,
]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<LatencyChartsDependencyResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -211,9 +203,7 @@ const dependencyThroughputChartsRoute = createApmServerRoute({
offsetRt,
]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ThroughputChartsForDependencyResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -257,9 +247,7 @@ const dependencyFailedTransactionRateChartsRoute = createApmServerRoute({
offsetRt,
]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -295,9 +283,7 @@ const dependencyFailedTransactionRateChartsRoute = createApmServerRoute({
const dependencyOperationsRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/dependencies/operations',
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.type({
query: t.intersection([
rangeRt,
@ -354,9 +340,7 @@ const dependencyLatencyDistributionChartsRoute = createApmServerRoute({
environmentRt,
]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<DependencyLatencyDistributionResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -378,9 +362,7 @@ const dependencyLatencyDistributionChartsRoute = createApmServerRoute({
const topDependencySpansRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/dependencies/operations/spans',
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.type({
query: t.intersection([
rangeRt,

View file

@ -80,7 +80,7 @@ export type DiagnosticsBundle = Promise<{
const getDiagnosticsRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/diagnostics',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.partial({
query: t.partial({
kuery: t.string,

View file

@ -18,7 +18,7 @@ const serviceEntitiesSummaryRoute = createApmServerRoute({
path: t.type({ serviceName: t.string }),
query: environmentRt,
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
async handler(resources) {
const { context, params, request } = resources;
const coreContext = await context.core;
@ -44,7 +44,7 @@ const servicesEntitiesRoute = createApmServerRoute({
params: t.type({
query: t.intersection([environmentRt, kueryRt, rangeRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
async handler(resources) {
const { context, params, request } = resources;
const coreContext = await context.core;
@ -77,7 +77,7 @@ const serviceLogRateTimeseriesRoute = createApmServerRoute({
}),
query: t.intersection([environmentRt, kueryRt, rangeRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
async handler(resources) {
const { context, params, plugins } = resources;
const [coreContext, logsDataAccessStart] = await Promise.all([
@ -111,7 +111,7 @@ const serviceLogErrorRateTimeseriesRoute = createApmServerRoute({
}),
query: t.intersection([environmentRt, kueryRt, rangeRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
async handler(resources) {
const { context, params, plugins } = resources;
const [coreContext, logsDataAccessStart] = await Promise.all([

View file

@ -24,7 +24,7 @@ const environmentsRoute = createApmServerRoute({
rangeRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{

View file

@ -51,7 +51,7 @@ const errorsMainStatisticsRoute = createApmServerRoute({
rangeRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ErrorGroupMainStatisticsResponse> => {
const { params } = resources;
const apmEventClient = await getApmEventClient(resources);
@ -90,7 +90,7 @@ const errorsMainStatisticsByTransactionNameRoute = createApmServerRoute({
rangeRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ErrorGroupMainStatisticsResponse> => {
const { params } = resources;
const apmEventClient = await getApmEventClient(resources);
@ -136,7 +136,7 @@ const errorsDetailedStatisticsRoute = createApmServerRoute({
]),
body: t.type({ groupIds: jsonRt.pipe(t.array(t.string)) }),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ErrorGroupPeriodsResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -170,7 +170,7 @@ const errorGroupsSamplesRoute = createApmServerRoute({
}),
query: t.intersection([environmentRt, kueryRt, rangeRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ErrorGroupSampleIdsResponse> => {
const { params } = resources;
const apmEventClient = await getApmEventClient(resources);
@ -199,7 +199,7 @@ const errorGroupSampleDetailsRoute = createApmServerRoute({
}),
query: t.intersection([environmentRt, kueryRt, rangeRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ErrorSampleDetailsResponse> => {
const { params } = resources;
const apmEventClient = await getApmEventClient(resources);
@ -240,7 +240,7 @@ const errorDistributionRoute = createApmServerRoute({
offsetRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ErrorDistributionResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -276,7 +276,7 @@ const topErroneousTransactionsRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<TopErroneousTransactionsResponse> => {
const { params } = resources;
const apmEventClient = await getApmEventClient(resources);

View file

@ -14,7 +14,7 @@ import { rangeRt } from '../default_api_types';
const eventMetadataRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/event_metadata/{processorEvent}/{id}',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.type({
path: t.type({
processorEvent: processorEventRt,

View file

@ -16,7 +16,7 @@ const fallbackToTransactionsRoute = createApmServerRoute({
params: t.partial({
query: t.intersection([kueryRt, t.partial(rangeRt.props)]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ fallbackToTransactions: boolean }> => {
const apmEventClient = await getApmEventClient(resources);
const {

View file

@ -65,7 +65,11 @@ const fleetAgentsRoute = createApmServerRoute({
const saveApmServerSchemaRoute = createApmServerRoute({
endpoint: 'POST /api/apm/fleet/apm_server_schema 2023-10-31',
options: { tags: ['access:apm', 'access:apm_write'] },
security: {
authz: {
requiredPrivileges: ['apm', 'apm_write'],
},
},
params: t.type({
body: t.type({
schema: t.record(t.string, t.unknown),
@ -88,7 +92,7 @@ const saveApmServerSchemaRoute = createApmServerRoute({
const getUnsupportedApmServerSchemaRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/fleet/apm_server_schema/unsupported',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ unsupported: UnsupportedApmServerSchema }> => {
throwNotFoundIfFleetMigrationNotAvailable(resources.featureFlags);
const { context } = resources;
@ -101,7 +105,7 @@ const getUnsupportedApmServerSchemaRoute = createApmServerRoute({
const getMigrationCheckRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/fleet/migration_check',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<RunMigrationCheckResponse> => {
const { core, plugins, context, config, request } = resources;
throwNotFoundIfFleetMigrationNotAvailable(resources.featureFlags);
@ -128,7 +132,11 @@ const getMigrationCheckRoute = createApmServerRoute({
const createCloudApmPackagePolicyRoute = createApmServerRoute({
endpoint: 'POST /internal/apm/fleet/cloud_apm_package_policy',
options: { tags: ['access:apm', 'access:apm_write'] },
security: {
authz: {
requiredPrivileges: ['apm', 'apm_write'],
},
},
handler: async (
resources
): Promise<{

View file

@ -13,7 +13,7 @@ import { hasEntitiesData } from './has_historical_entities_data';
const hasDataRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/has_data',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ hasData: boolean }> => {
const apmEventClient = await getApmEventClient(resources);
const hasData = await hasHistoricalAgentData(apmEventClient);
@ -23,7 +23,7 @@ const hasDataRoute = createApmServerRoute({
const hasEntitiesRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/has_entities',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ hasData: boolean }> => {
const { context, request, logger } = resources;
const coreContext = await context.core;

View file

@ -20,7 +20,7 @@ const infrastructureRoute = createApmServerRoute({
}),
query: t.intersection([kueryRt, rangeRt, environmentRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{

View file

@ -47,7 +47,7 @@ const latencyOverallTransactionDistributionRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<OverallLatencyDistributionResponse> => {
const apmEventClient = await getApmEventClient(resources);

View file

@ -32,7 +32,7 @@ const metricsChartsRoute = createApmServerRoute({
rangeRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -67,7 +67,7 @@ const serviceMetricsJvm = createApmServerRoute({
}),
query: t.intersection([kueryRt, rangeRt, environmentRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ serviceNodes: ServiceNodesResponse }> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;

View file

@ -46,7 +46,7 @@ const serverlessMetricsChartsRoute = createApmServerRoute({
t.intersection([transactionDataSourceRt, t.type({ bucketSizeInSeconds: toNumberRt })]),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -93,7 +93,7 @@ const serverlessMetricsActiveInstancesRoute = createApmServerRoute({
}),
query: t.intersection([environmentRt, kueryRt, rangeRt, t.partial({ serverlessId: t.string })]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -132,7 +132,7 @@ const serverlessMetricsFunctionsOverviewRoute = createApmServerRoute({
}),
query: t.intersection([environmentRt, kueryRt, rangeRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -164,7 +164,7 @@ const serverlessMetricsSummaryRoute = createApmServerRoute({
}),
query: t.intersection([environmentRt, kueryRt, rangeRt, t.partial({ serverlessId: t.string })]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ServerlessSummaryResponse> => {
const { params, context } = resources;
const {

View file

@ -36,7 +36,7 @@ const mobileCrashDistributionRoute = createApmServerRoute({
offsetRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<CrashDistributionResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -71,7 +71,7 @@ const mobileCrashMainStatisticsRoute = createApmServerRoute({
rangeRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ errorGroups: MobileCrashGroupMainStatisticsResponse }> => {
const { params } = resources;
const apmEventClient = await getApmEventClient(resources);
@ -110,7 +110,7 @@ const mobileCrashDetailedStatisticsRoute = createApmServerRoute({
]),
body: t.type({ groupIds: jsonRt.pipe(t.array(t.string)) }),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<MobileCrashesGroupPeriodsResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;

View file

@ -39,7 +39,7 @@ const mobileMobileHttpRatesRoute = createApmServerRoute({
}),
query: t.intersection([environmentRt, kueryRt, rangeRt, offsetRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<MobileHttpErrorsTimeseries> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -76,7 +76,7 @@ const mobileErrorsDetailedStatisticsRoute = createApmServerRoute({
]),
body: t.type({ groupIds: jsonRt.pipe(t.array(t.string)) }),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<MobileErrorGroupPeriodsResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -117,7 +117,7 @@ const mobileErrorTermsByFieldRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -158,7 +158,7 @@ const mobileErrorsMainStatisticsRoute = createApmServerRoute({
rangeRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ errorGroups: MobileErrorGroupMainStatisticsResponse }> => {
const { params } = resources;
const apmEventClient = await getApmEventClient(resources);

View file

@ -48,7 +48,7 @@ const mobileFiltersRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -87,7 +87,7 @@ const mobileChartsRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -131,7 +131,7 @@ const mobileStatsRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<MobilePeriodStats> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -168,7 +168,7 @@ const mobileLocationStatsRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<MobileLocationStats> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -207,7 +207,7 @@ const sessionsChartRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<SessionsTimeseries> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -246,7 +246,7 @@ const httpRequestsChartRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<HttpRequestsTimeseries> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -284,7 +284,7 @@ const mobileTermsByFieldRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -324,9 +324,7 @@ const mobileMainStatisticsByField = createApmServerRoute({
}),
]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<MobileMainStatisticsResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -362,9 +360,7 @@ const mobileDetailedStatisticsByField = createApmServerRoute({
}),
]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<MobileDetailedStatisticsResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;

View file

@ -19,7 +19,7 @@ import { getHasData, HasDataResponse } from './has_data';
const observabilityOverviewHasDataRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/observability_overview/has_data',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<HasDataResponse> => {
const apmEventClient = await getApmEventClient(resources);
return await getHasData({
@ -34,7 +34,7 @@ const observabilityOverviewRoute = createApmServerRoute({
params: t.type({
query: t.intersection([rangeRt, t.type({ bucketSize: toNumberRt, intervalString: t.string })]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ObservabilityOverviewResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { bucketSize, intervalString, start, end } = resources.params.query;

View file

@ -28,7 +28,7 @@ const profilingHostsFlamegraphRoute = createApmServerRoute({
path: t.type({ serviceName: t.string }),
query: t.intersection([rangeRt, environmentRt, serviceTransactionDataSourceRt, kueryRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<
@ -92,7 +92,7 @@ const profilingHostsFunctionsRoute = createApmServerRoute({
kueryRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<

View file

@ -33,7 +33,7 @@ const servicesFlamegraphRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<BaseFlameGraph | undefined> => {
const { context, plugins, params } = resources;
const core = await context.core;
@ -87,7 +87,7 @@ const servicesFunctionsRoute = createApmServerRoute({
kueryRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<TopNFunctions | undefined> => {
const { context, plugins, params } = resources;
const core = await context.core;
@ -136,7 +136,7 @@ const servicesFunctionsRoute = createApmServerRoute({
const profilingStatusRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/profiling/status',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ initialized: boolean }> => {
const { context, plugins, logger } = resources;
const [esClient, profilingDataAccessStart] = await Promise.all([

View file

@ -25,9 +25,7 @@ import { getApmAlertsClient } from '../../lib/helpers/get_apm_alerts_client';
const serviceGroupsRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/service-groups',
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ serviceGroups: SavedServiceGroup[] }> => {
const { context } = resources;
const {
@ -47,9 +45,7 @@ const serviceGroupRoute = createApmServerRoute({
serviceGroup: t.string,
}),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ serviceGroup: SavedServiceGroup }> => {
const { context, params } = resources;
const {
@ -79,7 +75,11 @@ const serviceGroupSaveRoute = createApmServerRoute({
color: t.union([t.string, t.undefined]),
}),
}),
options: { tags: ['access:apm', 'access:apm_write'] },
security: {
authz: {
requiredPrivileges: ['apm', 'apm_write'],
},
},
handler: async (resources): Promise<SavedServiceGroup> => {
const { context, params } = resources;
const { serviceGroupId } = params.query;
@ -106,7 +106,11 @@ const serviceGroupDeleteRoute = createApmServerRoute({
serviceGroupId: t.string,
}),
}),
options: { tags: ['access:apm', 'access:apm_write'] },
security: {
authz: {
requiredPrivileges: ['apm', 'apm_write'],
},
},
handler: async (resources): Promise<void> => {
const { context, params } = resources;
const { serviceGroupId } = params.query;
@ -123,9 +127,7 @@ const serviceGroupServicesRoute = createApmServerRoute({
params: t.type({
query: t.intersection([rangeRt, t.partial(kueryRt.props)]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ items: LookupServicesResponse }> => {
const { params, context } = resources;
const { kuery = '', start, end } = params.query;
@ -149,9 +151,7 @@ const serviceGroupServicesRoute = createApmServerRoute({
type ServiceGroupCounts = Record<string, { services: number; alerts: number }>;
const serviceGroupCountsRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/service-group/counts',
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ServiceGroupCounts> => {
const { context, logger, plugins, request } = resources;
const {

View file

@ -42,7 +42,7 @@ const serviceMapRoute = createApmServerRoute({
rangeRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<TransformServiceMapResponse> => {
const { config, context, params, logger } = resources;
if (!config.serviceMapEnabled) {
@ -111,7 +111,7 @@ const serviceMapServiceNodeRoute = createApmServerRoute({
}),
query: t.intersection([environmentRt, rangeRt, offsetRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ServiceMapServiceNodeInfoResponse> => {
const { config, context, params } = resources;
@ -154,7 +154,7 @@ const serviceMapDependencyNodeRoute = createApmServerRoute({
params: t.type({
query: t.intersection([t.type({ dependencyName: t.string }), environmentRt, rangeRt, offsetRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ServiceMapServiceDependencyInfoResponse> => {
const { config, context, params } = resources;

View file

@ -104,7 +104,7 @@ const servicesRoute = createApmServerRoute({
]),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
async handler(resources): Promise<ServicesItemsResponse> {
const {
context,
@ -172,7 +172,7 @@ const servicesDetailedStatisticsRoute = createApmServerRoute({
]),
body: t.type({ serviceNames: jsonRt.pipe(t.array(t.string)) }),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ServiceTransactionDetailedStatPeriodsResponse> => {
const {
params,
@ -225,7 +225,7 @@ const serviceMetadataDetailsRoute = createApmServerRoute({
path: t.type({ serviceName: t.string }),
query: t.intersection([rangeRt, environmentRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ServiceMetadataDetails> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -262,7 +262,7 @@ const serviceMetadataIconsRoute = createApmServerRoute({
path: t.type({ serviceName: t.string }),
query: rangeRt,
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ServiceMetadataIcons> => {
const apmEventClient = await getApmEventClient(resources);
const { params, config } = resources;
@ -295,7 +295,7 @@ const serviceAgentRoute = createApmServerRoute({
}),
query: rangeRt,
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ServiceAgentResponse> => {
const { context, request } = resources;
const coreContext = await context.core;
@ -339,7 +339,7 @@ const serviceTransactionTypesRoute = createApmServerRoute({
}),
query: t.intersection([rangeRt, serviceTransactionDataSourceRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ServiceTransactionTypesResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -366,7 +366,7 @@ const serviceNodeMetadataRoute = createApmServerRoute({
}),
query: t.intersection([kueryRt, rangeRt, environmentRt, serviceTransactionDataSourceRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ServiceNodeMetadataResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -395,7 +395,12 @@ const serviceAnnotationsRoute = createApmServerRoute({
}),
query: t.intersection([environmentRt, rangeRt]),
}),
options: { tags: ['access:apm', 'oas-tag:APM annotations'] },
options: { tags: ['oas-tag:APM annotations'] },
security: {
authz: {
requiredPrivileges: ['apm'],
},
},
handler: async (resources): Promise<ServiceAnnotationResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params, plugins, context, request, logger, config } = resources;
@ -439,7 +444,12 @@ const serviceAnnotationsRoute = createApmServerRoute({
const serviceAnnotationsCreateRoute = createApmServerRoute({
endpoint: 'POST /api/apm/services/{serviceName}/annotation 2023-10-31',
options: {
tags: ['access:apm', 'access:apm_write', 'oas-tag:APM annotations'],
tags: ['oas-tag:APM annotations'],
},
security: {
authz: {
requiredPrivileges: ['apm', 'apm_write'],
},
},
params: t.type({
path: t.type({
@ -523,7 +533,7 @@ const serviceThroughputRoute = createApmServerRoute({
t.intersection([environmentRt, kueryRt, rangeRt, offsetRt, serviceTransactionDataSourceRt]),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -605,7 +615,7 @@ const serviceInstancesMainStatisticsRoute = createApmServerRoute({
rangeRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -678,7 +688,7 @@ const serviceInstancesDetailedStatisticsRoute = createApmServerRoute({
offsetRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ServiceInstancesDetailedStatisticsResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params, config } = resources;
@ -730,7 +740,7 @@ export const serviceInstancesMetadataDetails = createApmServerRoute({
}),
query: rangeRt,
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<
@ -780,9 +790,7 @@ export const serviceDependenciesRoute = createApmServerRoute({
offsetRt,
]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
async handler(resources): Promise<{ serviceDependencies: ServiceDependenciesResponse }> {
const {
params,
@ -821,9 +829,7 @@ export const serviceDependenciesBreakdownRoute = createApmServerRoute({
}),
query: t.intersection([environmentRt, rangeRt, kueryRt]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -867,9 +873,7 @@ const serviceAnomalyChartsRoute = createApmServerRoute({
}),
query: t.intersection([rangeRt, environmentRt, t.type({ transactionType: t.string })]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -921,7 +925,7 @@ const serviceAlertsRoute = createApmServerRoute({
}),
query: t.intersection([rangeRt, environmentRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ServiceAlertsResponse[number]> => {
const { params } = resources;
const {

View file

@ -39,7 +39,7 @@ function throwNotFoundIfAgentConfigNotAvailable(featureFlags: ApmFeatureFlags):
// get list of configurations
const agentConfigurationRoute = createApmServerRoute({
endpoint: 'GET /api/apm/settings/agent-configuration 2023-10-31',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -68,7 +68,7 @@ const getSingleAgentConfigurationRoute = createApmServerRoute({
params: t.partial({
query: serviceRt,
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<AgentConfiguration> => {
throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags);
@ -98,8 +98,10 @@ const getSingleAgentConfigurationRoute = createApmServerRoute({
// delete configuration
const deleteAgentConfigurationRoute = createApmServerRoute({
endpoint: 'DELETE /api/apm/settings/agent-configuration 2023-10-31',
options: {
tags: ['access:apm', 'access:apm_settings_write'],
security: {
authz: {
requiredPrivileges: ['apm', 'apm_settings_write'],
},
},
params: t.type({
body: t.type({
@ -154,8 +156,10 @@ const deleteAgentConfigurationRoute = createApmServerRoute({
// create/update configuration
const createOrUpdateAgentConfigurationRoute = createApmServerRoute({
endpoint: 'PUT /api/apm/settings/agent-configuration 2023-10-31',
options: {
tags: ['access:apm', 'access:apm_settings_write'],
security: {
authz: {
requiredPrivileges: ['apm', 'apm_settings_write'],
},
},
params: t.intersection([
t.partial({ query: t.partial({ overwrite: toBooleanRt }) }),
@ -224,7 +228,12 @@ const agentConfigurationSearchRoute = createApmServerRoute({
params: t.type({
body: searchParamsRt,
}),
options: { tags: ['access:apm'], disableTelemetry: true },
options: { disableTelemetry: true },
security: {
authz: {
requiredPrivileges: ['apm'],
},
},
handler: async (
resources
): Promise<SearchHit<AgentConfiguration, undefined, undefined> | null> => {
@ -286,7 +295,7 @@ const listAgentConfigurationEnvironmentsRoute = createApmServerRoute({
params: t.partial({
query: t.partial({ serviceName: t.string }),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -327,7 +336,7 @@ const agentConfigurationAgentNameRoute = createApmServerRoute({
params: t.type({
query: t.type({ serviceName: t.string }),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ agentName: string | undefined }> => {
throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags);

View file

@ -26,8 +26,10 @@ import { ApmMlJob } from '../../../../common/anomaly_detection/apm_ml_job';
// get ML anomaly detection jobs for each environment
const anomalyDetectionJobsRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/settings/anomaly-detection/jobs',
options: {
tags: ['access:apm', 'access:ml:canGetJobs'],
security: {
authz: {
requiredPrivileges: ['apm', 'ml:canGetJobs'],
},
},
handler: async (
resources
@ -59,8 +61,10 @@ const anomalyDetectionJobsRoute = createApmServerRoute({
// create new ML anomaly detection jobs for each given environment
const createAnomalyDetectionJobsRoute = createApmServerRoute({
endpoint: 'POST /internal/apm/settings/anomaly-detection/jobs',
options: {
tags: ['access:apm', 'access:apm_settings_write', 'access:ml:canCreateJob'],
security: {
authz: {
requiredPrivileges: ['apm', 'apm_settings_write', 'ml:canCreateJob'],
},
},
params: t.type({
body: t.type({
@ -102,7 +106,7 @@ const createAnomalyDetectionJobsRoute = createApmServerRoute({
// get all available environments to create anomaly detection jobs for
const anomalyDetectionEnvironmentsRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/settings/anomaly-detection/environments',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ environments: string[] }> => {
const apmEventClient = await getApmEventClient(resources);
const coreContext = await resources.context.core;
@ -126,14 +130,16 @@ const anomalyDetectionEnvironmentsRoute = createApmServerRoute({
const anomalyDetectionUpdateToV3Route = createApmServerRoute({
endpoint: 'POST /internal/apm/settings/anomaly-detection/update_to_v3',
options: {
tags: [
'access:apm',
'access:apm_settings_write',
'access:ml:canCreateJob',
'access:ml:canGetJobs',
'access:ml:canCloseJob',
],
security: {
authz: {
requiredPrivileges: [
'apm',
'apm_settings_write',
'ml:canCreateJob',
'ml:canGetJobs',
'ml:canCloseJob',
],
},
},
handler: async (resources): Promise<{ update: boolean }> => {
const { getApmIndices } = resources;

View file

@ -15,7 +15,7 @@ import { getApmIndexSettings, ApmIndexSettingsResponse } from './get_apm_indices
// get list of apm indices and values
const apmIndexSettingsRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/settings/apm-index-settings',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -29,7 +29,7 @@ const apmIndexSettingsRoute = createApmServerRoute({
// get apm indices configuration object
const apmIndicesRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/settings/apm-indices',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<APMIndices> => {
return await resources.getApmIndices();
},
@ -42,8 +42,10 @@ type SaveApmIndicesBodySchema = {
// save ui indices
const saveApmIndicesRoute = createApmServerRoute({
endpoint: 'POST /internal/apm/settings/apm-indices/save',
options: {
tags: ['access:apm', 'access:apm_settings_write'],
security: {
authz: {
requiredPrivileges: ['apm', 'apm_settings_write'],
},
},
params: t.type({
body: t.partial({

View file

@ -25,7 +25,7 @@ import { CustomLink } from '../../../../common/custom_link/custom_link_types';
const customLinkTransactionRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/settings/custom_links/transaction',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.partial({
query: filterOptionsRt,
}),
@ -41,7 +41,7 @@ const customLinkTransactionRoute = createApmServerRoute({
const listCustomLinksRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/settings/custom_links',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.partial({
query: filterOptionsRt,
}),
@ -75,7 +75,11 @@ const createCustomLinkRoute = createApmServerRoute({
params: t.type({
body: payloadRt,
}),
options: { tags: ['access:apm', 'access:apm_settings_write'] },
security: {
authz: {
requiredPrivileges: ['apm', 'apm_settings_write'],
},
},
handler: async (resources): Promise<void> => {
const { context, params } = resources;
const licensingContext = await context.licensing;
@ -104,8 +108,10 @@ const updateCustomLinkRoute = createApmServerRoute({
}),
body: payloadRt,
}),
options: {
tags: ['access:apm', 'access:apm_settings_write'],
security: {
authz: {
requiredPrivileges: ['apm', 'apm_settings_write'],
},
},
handler: async (resources): Promise<void> => {
const { params, context } = resources;
@ -135,8 +141,10 @@ const deleteCustomLinkRoute = createApmServerRoute({
id: t.string,
}),
}),
options: {
tags: ['access:apm', 'access:apm_settings_write'],
security: {
authz: {
requiredPrivileges: ['apm', 'apm_settings_write'],
},
},
handler: async (resources): Promise<{ result: string }> => {
const { context, params } = resources;

View file

@ -10,7 +10,7 @@ import { createApmServerRoute } from '../../apm_routes/create_apm_server_route';
const getLabsRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/settings/labs',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (): Promise<{ labsItems: string[] }> => {
const labsItems = Object.entries(uiSettings)
.filter(([key, value]): boolean | undefined => value.showInLabs)

View file

@ -49,7 +49,7 @@ function throwNotImplementedIfSourceMapNotAvailable(featureFlags: ApmFeatureFlag
const listSourceMapRoute = createApmServerRoute({
endpoint: 'GET /api/apm/sourcemaps 2023-10-31',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.partial({
query: t.partial({
page: toNumberRt,
@ -85,9 +85,13 @@ const listSourceMapRoute = createApmServerRoute({
const uploadSourceMapRoute = createApmServerRoute({
endpoint: 'POST /api/apm/sourcemaps 2023-10-31',
options: {
tags: ['access:apm', 'access:apm_write'],
body: { accepts: ['multipart/form-data'] },
},
security: {
authz: {
requiredPrivileges: ['apm', 'apm_write'],
},
},
params: t.type({
body: t.type({
service_name: t.string,
@ -159,7 +163,11 @@ const uploadSourceMapRoute = createApmServerRoute({
const deleteSourceMapRoute = createApmServerRoute({
endpoint: 'DELETE /api/apm/sourcemaps/{id} 2023-10-31',
options: { tags: ['access:apm', 'access:apm_write'] },
security: {
authz: {
requiredPrivileges: ['apm', 'apm_write'],
},
},
params: t.type({
path: t.type({
id: t.string,
@ -192,7 +200,11 @@ const deleteSourceMapRoute = createApmServerRoute({
const migrateFleetArtifactsSourceMapRoute = createApmServerRoute({
endpoint: 'POST /internal/apm/sourcemaps/migrate_fleet_artifacts',
options: { tags: ['access:apm', 'access:apm_write'] },
security: {
authz: {
requiredPrivileges: ['apm', 'apm_write'],
},
},
handler: async ({ plugins, core, logger, featureFlags }): Promise<void> => {
throwNotImplementedIfSourceMapNotAvailable(featureFlags);

View file

@ -23,7 +23,7 @@ const linkedParentsRoute = createApmServerRoute({
}),
query: t.intersection([kueryRt, rangeRt, t.type({ processorEvent: processorEventRt })]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -63,7 +63,7 @@ const linkedChildrenRoute = createApmServerRoute({
}),
query: t.intersection([kueryRt, rangeRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{

View file

@ -34,7 +34,7 @@ import { isCrossClusterSearch } from './is_cross_cluster_search';
const storageExplorerRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/storage_explorer',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.type({
query: t.intersection([indexLifecyclePhaseRt, probabilityRt, environmentRt, kueryRt, rangeRt]),
}),
@ -86,7 +86,7 @@ const storageExplorerRoute = createApmServerRoute({
const storageExplorerServiceDetailsRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/services/{serviceName}/storage_details',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.type({
path: t.type({
serviceName: t.string,
@ -127,7 +127,7 @@ const storageExplorerServiceDetailsRoute = createApmServerRoute({
const storageChartRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/storage_chart',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.type({
query: t.intersection([indexLifecyclePhaseRt, probabilityRt, environmentRt, kueryRt, rangeRt]),
}),
@ -177,7 +177,7 @@ const storageChartRoute = createApmServerRoute({
const storageExplorerPrivilegesRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/storage_explorer/privileges',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ hasPrivileges: boolean }> => {
const {
@ -201,7 +201,7 @@ const storageExplorerPrivilegesRoute = createApmServerRoute({
const storageExplorerSummaryStatsRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/storage_explorer_summary_stats',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.type({
query: t.intersection([indexLifecyclePhaseRt, probabilityRt, environmentRt, kueryRt, rangeRt]),
}),
@ -245,7 +245,7 @@ const storageExplorerSummaryStatsRoute = createApmServerRoute({
const storageExplorerIsCrossClusterSearchRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/storage_explorer/is_cross_cluster_search',
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ isCrossClusterSearch: boolean }> => {
const apmEventClient = await getApmEventClient(resources);
return { isCrossClusterSearch: isCrossClusterSearch(apmEventClient) };
@ -254,9 +254,7 @@ const storageExplorerIsCrossClusterSearchRoute = createApmServerRoute({
const storageExplorerGetServices = createApmServerRoute({
endpoint: 'GET /internal/apm/storage_explorer/get_services',
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
params: t.type({
query: t.intersection([indexLifecyclePhaseRt, environmentRt, kueryRt, rangeRt]),
}),

View file

@ -26,7 +26,7 @@ const suggestionsRoute = createApmServerRoute({
t.partial({ serviceName: t.string }),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ terms: string[] }> => {
const apmEventClient = await getApmEventClient(resources);
const { context, params, config } = resources;

View file

@ -26,9 +26,7 @@ export const timeRangeMetadataRoute = createApmServerRoute({
rangeRt,
]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<TimeRangeMetadata> => {
const apmEventClient = await getApmEventClient(resources);
const apmDataAccessServices = await getApmDataAccessServices({ apmEventClient, ...resources });

View file

@ -35,7 +35,7 @@ const tracesRoute = createApmServerRoute({
params: t.type({
query: t.intersection([environmentRt, kueryRt, rangeRt, probabilityRt]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<TopTracesPrimaryStatsResponse> => {
const {
config,
@ -83,7 +83,7 @@ const tracesByIdRoute = createApmServerRoute({
t.partial({ maxTraceItems: toNumberRt }),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -127,7 +127,7 @@ const rootTransactionByTraceIdRoute = createApmServerRoute({
}),
query: rangeRt,
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -154,7 +154,7 @@ const transactionByIdRoute = createApmServerRoute({
}),
query: rangeRt,
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -190,7 +190,7 @@ const transactionByNameRoute = createApmServerRoute({
}),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -227,9 +227,7 @@ const findTracesRoute = createApmServerRoute({
}),
]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{
@ -264,9 +262,7 @@ const aggregatedCriticalPathRoute = createApmServerRoute({
rangeRt,
]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<{ criticalPath: CriticalPathResponse | null }> => {
const {
params: {
@ -297,7 +293,7 @@ const transactionFromTraceByIdRoute = createApmServerRoute({
}),
query: rangeRt,
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<Transaction | undefined> => {
const { params } = resources;
const {
@ -328,7 +324,7 @@ const spanFromTraceByIdRoute = createApmServerRoute({
t.union([t.partial({ parentTransactionId: t.string }), t.undefined]),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (
resources
): Promise<{

View file

@ -75,9 +75,7 @@ const transactionGroupsMainStatisticsRoute = createApmServerRoute({
transactionDataSourceRt,
]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<MergedServiceTransactionGroupsResponse> => {
const { params } = resources;
const apmEventClient = await getApmEventClient(resources);
@ -164,9 +162,7 @@ const transactionGroupsDetailedStatisticsRoute = createApmServerRoute({
}),
]),
}),
options: {
tags: ['access:apm'],
},
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ServiceTransactionGroupDetailedStatisticsResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -226,7 +222,7 @@ const transactionLatencyChartsRoute = createApmServerRoute({
serviceTransactionDataSourceRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<TransactionLatencyResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params, logger } = resources;
@ -295,7 +291,7 @@ const transactionTraceSamplesRoute = createApmServerRoute({
rangeRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<TransactionTraceSamplesResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params } = resources;
@ -344,7 +340,7 @@ const transactionChartsBreakdownRoute = createApmServerRoute({
rangeRt,
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<TransactionBreakdownResponse> => {
const apmEventClient = await getApmEventClient(resources);
const { params, config } = resources;
@ -378,7 +374,7 @@ const transactionChartsErrorRateRoute = createApmServerRoute({
t.intersection([environmentRt, kueryRt, rangeRt, offsetRt, serviceTransactionDataSourceRt]),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<FailedTransactionRateResponse> => {
const apmEventClient = await getApmEventClient(resources);
@ -427,7 +423,7 @@ const transactionChartsColdstartRateRoute = createApmServerRoute({
t.intersection([environmentRt, kueryRt, rangeRt, offsetRt]),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ColdstartRateResponse> => {
const apmEventClient = await getApmEventClient(resources);
@ -469,7 +465,7 @@ const transactionChartsColdstartRateByTransactionNameRoute = createApmServerRout
t.intersection([environmentRt, kueryRt, rangeRt, offsetRt]),
]),
}),
options: { tags: ['access:apm'] },
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<ColdstartRateResponse> => {
const apmEventClient = await getApmEventClient(resources);

View file

@ -45,17 +45,7 @@ export type MinimalApmPluginRequestHandlerContext = Omit<
};
export interface APMRouteCreateOptions {
tags: Array<
| 'access:apm'
| 'access:apm_write'
| 'access:apm_settings_write'
| 'access:ml:canGetJobs'
| 'access:ml:canCreateJob'
| 'access:ml:canCloseJob'
| 'access:ai_assistant'
| 'oas-tag:APM agent keys'
| 'oas-tag:APM annotations'
>;
tags?: Array<'oas-tag:APM agent keys' | 'oas-tag:APM annotations'>;
disableTelemetry?: boolean;
}

View file

@ -38,7 +38,9 @@ export default function apiTest({ getService }: FtrProviderContext) {
const err = await expectToReject<ApmApiError>(() => getJobs());
expect(err.res.status).to.be(403);
expect(err.res.body.message).eql('Forbidden');
expect(err.res.body.message).eql(
'API [GET /internal/apm/settings/anomaly-detection/jobs] is unauthorized for user, this action is granted by the Kibana privileges [apm,ml:canGetJobs]'
);
});
});
@ -49,7 +51,9 @@ export default function apiTest({ getService }: FtrProviderContext) {
);
expect(err.res.status).to.be(403);
expect(err.res.body.message).eql('Forbidden');
expect(err.res.body.message).eql(
'API [POST /internal/apm/settings/anomaly-detection/jobs] is unauthorized for user, this action is granted by the Kibana privileges [apm,apm_settings_write,ml:canCreateJob]'
);
});
});
});