mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[kbn/server-route-repository] Make security required (#216196)
To mirror the changes in https://github.com/elastic/kibana/pull/215180
This commit is contained in:
parent
4f79e2480a
commit
53263fd9fc
7 changed files with 81 additions and 15 deletions
|
@ -11,6 +11,13 @@ import * as t from 'io-ts';
|
|||
import { CoreSetup } from '@kbn/core-lifecycle-browser';
|
||||
import { createRepositoryClient } from './create_repository_client';
|
||||
|
||||
const disabledAuthz = {
|
||||
authz: {
|
||||
enabled: false as const,
|
||||
reason: 'This is a test',
|
||||
},
|
||||
};
|
||||
|
||||
describe('createRepositoryClient', () => {
|
||||
const getMock = jest.fn();
|
||||
const coreSetupMock = {
|
||||
|
@ -28,6 +35,7 @@ describe('createRepositoryClient', () => {
|
|||
'GET /internal/handler': {
|
||||
endpoint: 'GET /internal/handler',
|
||||
handler: jest.fn().mockResolvedValue('OK'),
|
||||
security: disabledAuthz,
|
||||
},
|
||||
};
|
||||
const { fetch } = createRepositoryClient<typeof repository>(coreSetupMock);
|
||||
|
@ -47,6 +55,7 @@ describe('createRepositoryClient', () => {
|
|||
'GET /api/handler 2024-08-05': {
|
||||
endpoint: 'GET /api/handler 2024-08-05',
|
||||
handler: jest.fn().mockResolvedValue('OK'),
|
||||
security: disabledAuthz,
|
||||
},
|
||||
};
|
||||
const { fetch } = createRepositoryClient<typeof repository>(coreSetupMock);
|
||||
|
@ -66,6 +75,7 @@ describe('createRepositoryClient', () => {
|
|||
'GET /internal/handler': {
|
||||
endpoint: 'GET /internal/handler',
|
||||
handler: jest.fn().mockResolvedValue('OK'),
|
||||
security: disabledAuthz,
|
||||
},
|
||||
};
|
||||
const { fetch } = createRepositoryClient<typeof repository>(coreSetupMock);
|
||||
|
@ -97,6 +107,7 @@ describe('createRepositoryClient', () => {
|
|||
}),
|
||||
}),
|
||||
handler: jest.fn().mockResolvedValue('OK'),
|
||||
security: disabledAuthz,
|
||||
},
|
||||
};
|
||||
const { fetch } = createRepositoryClient<typeof repository>(coreSetupMock);
|
||||
|
@ -127,6 +138,7 @@ describe('createRepositoryClient', () => {
|
|||
}),
|
||||
}),
|
||||
handler: jest.fn().mockResolvedValue('OK'),
|
||||
security: disabledAuthz,
|
||||
},
|
||||
};
|
||||
const { fetch } = createRepositoryClient<typeof repository>(coreSetupMock);
|
||||
|
@ -159,6 +171,7 @@ describe('createRepositoryClient', () => {
|
|||
}),
|
||||
}),
|
||||
handler: jest.fn().mockResolvedValue('OK'),
|
||||
security: disabledAuthz,
|
||||
},
|
||||
};
|
||||
const { fetch } = createRepositoryClient<typeof repository>(coreSetupMock);
|
||||
|
|
|
@ -151,7 +151,7 @@ export type CreateServerRouteFactory<
|
|||
endpoint: ValidateEndpoint<TEndpoint, TRouteAccess> extends true ? TEndpoint : never;
|
||||
handler: ServerRouteHandler<TRouteHandlerResources, TRouteParamsRT, TReturnType>;
|
||||
params?: TRouteParamsRT;
|
||||
security?: RouteSecurity;
|
||||
security: RouteSecurity;
|
||||
} & Required<
|
||||
{
|
||||
options?: (TRouteCreateOptions extends DefaultRouteCreateOptions ? TRouteCreateOptions : {}) &
|
||||
|
@ -181,7 +181,7 @@ export type ServerRoute<
|
|||
> = {
|
||||
endpoint: TEndpoint;
|
||||
handler: ServerRouteHandler<TRouteHandlerResources, TRouteParamsRT, TReturnType>;
|
||||
security?: RouteSecurity;
|
||||
security: RouteSecurity;
|
||||
} & (TRouteParamsRT extends RouteParamsRT ? { params: TRouteParamsRT } : {}) &
|
||||
(TRouteCreateOptions extends DefaultRouteCreateOptions ? { options: TRouteCreateOptions } : {});
|
||||
|
||||
|
|
|
@ -17,6 +17,13 @@ import { registerRoutes } from './register_routes';
|
|||
import { passThroughValidationObject, noParamsValidationObject } from './validation_objects';
|
||||
import { ServerRouteRepository } from '@kbn/server-route-repository-utils';
|
||||
|
||||
const disabledAuthz = {
|
||||
authz: {
|
||||
enabled: false as const,
|
||||
reason: 'This is a test',
|
||||
},
|
||||
};
|
||||
|
||||
describe('registerRoutes', () => {
|
||||
const post = jest.fn();
|
||||
const postAddVersion = jest.fn();
|
||||
|
@ -55,10 +62,12 @@ describe('registerRoutes', () => {
|
|||
'POST /internal/route': {
|
||||
endpoint: 'POST /internal/route',
|
||||
handler: jest.fn(),
|
||||
security: disabledAuthz,
|
||||
},
|
||||
'POST /api/public_route version': {
|
||||
endpoint: 'POST /api/public_route version',
|
||||
handler: jest.fn(),
|
||||
security: disabledAuthz,
|
||||
},
|
||||
'POST /api/internal_but_looks_like_public version': {
|
||||
endpoint: 'POST /api/internal_but_looks_like_public version',
|
||||
|
@ -66,6 +75,7 @@ describe('registerRoutes', () => {
|
|||
access: 'internal',
|
||||
},
|
||||
handler: jest.fn(),
|
||||
security: disabledAuthz,
|
||||
},
|
||||
'POST /internal/route_with_security': {
|
||||
endpoint: `POST /internal/route_with_security`,
|
||||
|
|
|
@ -192,12 +192,7 @@ export function registerRoutes<TDependencies extends Record<string, any>>({
|
|||
...options,
|
||||
access,
|
||||
},
|
||||
security: security ?? {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'Delegates authorization to the es client',
|
||||
},
|
||||
},
|
||||
security,
|
||||
validate: validationObject,
|
||||
},
|
||||
wrappedHandler
|
||||
|
@ -209,12 +204,7 @@ export function registerRoutes<TDependencies extends Record<string, any>>({
|
|||
summary: options.summary,
|
||||
description: options.description,
|
||||
options: omit(options, 'access', 'description', 'summary', 'deprecated', 'discontinued'),
|
||||
security: security ?? {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'Delegates authorization to the es client',
|
||||
},
|
||||
},
|
||||
security,
|
||||
}).addVersion(
|
||||
{
|
||||
version,
|
||||
|
|
|
@ -15,6 +15,13 @@ import { Observable, of } from 'rxjs';
|
|||
import { createServerRouteFactory } from './create_server_route_factory';
|
||||
import { decodeRequestParams } from './decode_request_params';
|
||||
|
||||
const disabledAuthz = {
|
||||
authz: {
|
||||
enabled: false as const,
|
||||
reason: 'This is a test',
|
||||
},
|
||||
};
|
||||
|
||||
function assertType<TShape = never>(value: TShape) {
|
||||
return value;
|
||||
}
|
||||
|
@ -27,6 +34,7 @@ createServerRouteFactory<{}, {}>()({
|
|||
// @ts-expect-error Argument of type '{}' is not assignable to parameter of type '{ params: any; }'.
|
||||
assertType<{ params: any }>(resources);
|
||||
},
|
||||
security: disabledAuthz,
|
||||
});
|
||||
|
||||
// If a params codec is set, its type _should_ be available in the
|
||||
|
@ -41,6 +49,7 @@ createServerRouteFactory<{}, {}>()({
|
|||
handler: async (resources) => {
|
||||
assertType<{ params: { path: { serviceName: string } } }>(resources);
|
||||
},
|
||||
security: disabledAuthz,
|
||||
});
|
||||
|
||||
createServerRouteFactory<{}, {}>()({
|
||||
|
@ -53,6 +62,7 @@ createServerRouteFactory<{}, {}>()({
|
|||
handler: async (resources) => {
|
||||
assertType<{ params: { path: { serviceName: string } } }>(resources);
|
||||
},
|
||||
security: disabledAuthz,
|
||||
});
|
||||
|
||||
// Resources should be passed to the request handler.
|
||||
|
@ -67,6 +77,7 @@ createServerRouteFactory<{ context: { getSpaceId: () => string } }, {}>()({
|
|||
const spaceId = context.getSpaceId();
|
||||
assertType<string>(spaceId);
|
||||
},
|
||||
security: disabledAuthz,
|
||||
});
|
||||
|
||||
createServerRouteFactory<{ context: { getSpaceId: () => string } }, {}>()({
|
||||
|
@ -80,6 +91,7 @@ createServerRouteFactory<{ context: { getSpaceId: () => string } }, {}>()({
|
|||
const spaceId = context.getSpaceId();
|
||||
assertType<string>(spaceId);
|
||||
},
|
||||
security: disabledAuthz,
|
||||
});
|
||||
|
||||
// Create options are available when registering a route.
|
||||
|
@ -93,6 +105,7 @@ createServerRouteFactory<{}, {}>()({
|
|||
handler: async (resources) => {
|
||||
assertType<{ params: { path: { serviceName: string } } }>(resources);
|
||||
},
|
||||
security: disabledAuthz,
|
||||
});
|
||||
|
||||
// Public APIs should be versioned
|
||||
|
@ -101,6 +114,7 @@ createServerRouteFactory<{}, { tags: string[] }>()({
|
|||
endpoint: 'GET /api/endpoint_with_params',
|
||||
tags: [],
|
||||
handler: async (resources) => {},
|
||||
security: disabledAuthz,
|
||||
});
|
||||
|
||||
// `access` is respected
|
||||
|
@ -111,6 +125,7 @@ createServerRouteFactory<{}, { tags: string[] }>()({
|
|||
access: 'internal',
|
||||
},
|
||||
handler: async (resources) => {},
|
||||
security: disabledAuthz,
|
||||
});
|
||||
|
||||
// specifying additional options makes them required
|
||||
|
@ -118,6 +133,7 @@ createServerRouteFactory<{}, { tags: string[] }>()({
|
|||
createServerRouteFactory<{}, { tags: string[] }>()({
|
||||
endpoint: 'GET /api/endpoint_with_params 2023-10-31',
|
||||
handler: async (resources) => {},
|
||||
security: disabledAuthz,
|
||||
});
|
||||
|
||||
createServerRouteFactory<{}, { tags: string[] }>()({
|
||||
|
@ -126,6 +142,7 @@ createServerRouteFactory<{}, { tags: string[] }>()({
|
|||
tags: [],
|
||||
},
|
||||
handler: async (resources) => {},
|
||||
security: disabledAuthz,
|
||||
});
|
||||
|
||||
// cannot return observables that are not in the SSE structure
|
||||
|
@ -135,6 +152,7 @@ const route = createServerRouteFactory<{}, {}>()({
|
|||
handler: async () => {
|
||||
return of({ streamed_response: true });
|
||||
},
|
||||
security: disabledAuthz,
|
||||
});
|
||||
|
||||
const createServerRoute = createServerRouteFactory<{}, {}>();
|
||||
|
@ -147,6 +165,7 @@ const repository = {
|
|||
noParamsForMe: true,
|
||||
};
|
||||
},
|
||||
security: disabledAuthz,
|
||||
}),
|
||||
...createServerRoute({
|
||||
endpoint: 'GET /internal/endpoint_with_params',
|
||||
|
@ -160,6 +179,7 @@ const repository = {
|
|||
yesParamsForMe: true,
|
||||
};
|
||||
},
|
||||
security: disabledAuthz,
|
||||
}),
|
||||
...createServerRoute({
|
||||
endpoint: 'GET /internal/endpoint_with_optional_params',
|
||||
|
@ -173,6 +193,7 @@ const repository = {
|
|||
someParamsForMe: true,
|
||||
};
|
||||
},
|
||||
security: disabledAuthz,
|
||||
}),
|
||||
...createServerRoute({
|
||||
endpoint: 'GET /internal/endpoint_with_params_zod',
|
||||
|
@ -186,6 +207,7 @@ const repository = {
|
|||
yesParamsForMe: true,
|
||||
};
|
||||
},
|
||||
security: disabledAuthz,
|
||||
}),
|
||||
...createServerRoute({
|
||||
endpoint: 'GET /internal/endpoint_with_optional_params_zod',
|
||||
|
@ -203,6 +225,7 @@ const repository = {
|
|||
someParamsForMe: true,
|
||||
};
|
||||
},
|
||||
security: disabledAuthz,
|
||||
}),
|
||||
...createServerRoute({
|
||||
endpoint: 'GET /internal/endpoint_returning_result',
|
||||
|
@ -211,6 +234,7 @@ const repository = {
|
|||
result: true,
|
||||
};
|
||||
},
|
||||
security: disabledAuthz,
|
||||
}),
|
||||
...createServerRoute({
|
||||
endpoint: 'GET /internal/endpoint_returning_kibana_response',
|
||||
|
@ -221,12 +245,14 @@ const repository = {
|
|||
},
|
||||
});
|
||||
},
|
||||
security: disabledAuthz,
|
||||
}),
|
||||
...createServerRoute({
|
||||
endpoint: 'POST /internal/endpoint_returning_observable',
|
||||
handler: async () => {
|
||||
return of({ type: 'foo' as const, streamed_response: true });
|
||||
},
|
||||
security: disabledAuthz,
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,13 @@ export const listStreamsRoute = createServerRoute({
|
|||
access: 'internal',
|
||||
},
|
||||
params: z.object({}),
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason:
|
||||
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
|
||||
},
|
||||
},
|
||||
handler: async ({ request, getScopedClients }): Promise<{ streams: ListStreamDetail[] }> => {
|
||||
const { streamsClient, scopedClusterClient } = await getScopedClients({ request });
|
||||
const streams = await streamsClient.listStreams();
|
||||
|
|
|
@ -15,6 +15,13 @@ import type { APMRouteHandlerResources } from './register_apm_server_routes';
|
|||
import { registerRoutes } from './register_apm_server_routes';
|
||||
import { NEVER } from 'rxjs';
|
||||
|
||||
const disabledAuthz = {
|
||||
authz: {
|
||||
enabled: false as const,
|
||||
reason: 'This is a test',
|
||||
},
|
||||
};
|
||||
|
||||
type RegisterRouteDependencies = Parameters<typeof registerRoutes>[0];
|
||||
|
||||
const getRegisterRouteDependencies = () => {
|
||||
|
@ -223,6 +230,7 @@ describe('createApi', () => {
|
|||
endpoint: 'GET /foo',
|
||||
options: { tags: [] },
|
||||
handler: handlerMock,
|
||||
security: disabledAuthz,
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -256,6 +264,7 @@ describe('createApi', () => {
|
|||
tags: [],
|
||||
},
|
||||
handler: handlerMock,
|
||||
security: disabledAuthz,
|
||||
},
|
||||
]);
|
||||
await simulateRequest({
|
||||
|
@ -282,7 +291,14 @@ describe('createApi', () => {
|
|||
const {
|
||||
simulateRequest,
|
||||
mocks: { response },
|
||||
} = initApi([{ endpoint: 'GET /foo', options: { tags: [] }, handler: handlerMock }]);
|
||||
} = initApi([
|
||||
{
|
||||
endpoint: 'GET /foo',
|
||||
options: { tags: [] },
|
||||
handler: handlerMock,
|
||||
security: disabledAuthz,
|
||||
},
|
||||
]);
|
||||
await simulateRequest({
|
||||
method: 'get',
|
||||
pathname: '/foo',
|
||||
|
@ -309,6 +325,7 @@ describe('createApi', () => {
|
|||
endpoint: 'GET /foo',
|
||||
options: { tags: [] },
|
||||
handler: jest.fn().mockResolvedValue({}),
|
||||
security: disabledAuthz,
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -354,6 +371,7 @@ describe('createApi', () => {
|
|||
}),
|
||||
}),
|
||||
handler: handlerMock,
|
||||
security: disabledAuthz,
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -428,6 +446,7 @@ describe('createApi', () => {
|
|||
body: t.string,
|
||||
}),
|
||||
handler: handlerMock,
|
||||
security: disabledAuthz,
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -477,6 +496,7 @@ describe('createApi', () => {
|
|||
}),
|
||||
}),
|
||||
handler: handlerMock,
|
||||
security: disabledAuthz,
|
||||
},
|
||||
]);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue