Unauthorized route migration for routes owned by kibana-security (#198334)

### Authz API migration for unauthorized routes

This PR migrates unauthorized routes owned by your team to a new
security configuration.
Please refer to the documentation for more information: [Authorization
API](https://docs.elastic.dev/kibana-dev-docs/key-concepts/security-api-authorization)

### **Before migration:**
```ts
router.get({
  path: '/api/path',
  ...
}, handler);
```

### **After migration:**
```ts
router.get({
  path: '/api/path',
  security: {
    authz: {
      enabled: false,
      reason: 'This route is opted out from authorization because ...',
    },
  },
  ...
}, handler);
```

### What to do next?
1. Review the changes in this PR.
2. Elaborate on the reasoning to opt-out of authorization.
3. Routes without a compelling reason to opt-out of authorization should
plan to introduce them as soon as possible.
2. You might need to update your tests to reflect the new security
configuration:
  - If you have snapshot tests that include the route definition.

## Any questions?
If you have any questions or need help with API authorization, please
reach out to the `@elastic/kibana-security` team.

---------

Co-authored-by: “jeramysoucy” <jeramy.soucy@elastic.co>
Co-authored-by: Larry Gregory <larry.gregory@elastic.co>
Co-authored-by: Elena Shostak <165678770+elena-shostak@users.noreply.github.com>
Co-authored-by: Elena Shostak <elena.shostak@elastic.co>
This commit is contained in:
Kibana Machine 2024-11-08 08:04:16 +11:00 committed by GitHub
parent 0df2e98381
commit c994b48805
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
58 changed files with 483 additions and 16 deletions

View file

@ -37,6 +37,13 @@ export function defineConfigureRoute({
router.post(
{
path: '/internal/interactive_setup/configure',
security: {
authz: {
enabled: false,
reason:
'Interactive setup is strictly a "pre-boot" feature which cannot leverage conventional authorization.',
},
},
validate: {
body: schema.object({
host: schema.uri({ scheme: ['http', 'https'] }),

View file

@ -40,6 +40,13 @@ export function defineEnrollRoutes({
router.post(
{
path: '/internal/interactive_setup/enroll',
security: {
authz: {
enabled: false,
reason:
'Interactive setup is strictly a "pre-boot" feature which cannot leverage conventional authorization.',
},
},
validate: {
body: schema.object({
hosts: schema.arrayOf(schema.uri({ scheme: 'https' }), {

View file

@ -17,6 +17,13 @@ export function definePingRoute({ router, logger, elasticsearch, preboot }: Rout
router.post(
{
path: '/internal/interactive_setup/ping',
security: {
authz: {
enabled: false,
reason:
'Interactive setup is strictly a "pre-boot" feature which cannot leverage conventional authorization.',
},
},
validate: {
body: schema.object({
host: schema.uri({ scheme: ['http', 'https'] }),

View file

@ -15,6 +15,13 @@ export function defineStatusRoute({ router, elasticsearch, preboot }: RouteDefin
router.get(
{
path: '/internal/interactive_setup/status',
security: {
authz: {
enabled: false,
reason:
'Interactive setup is strictly a "pre-boot" feature which cannot leverage conventional authorization.',
},
},
validate: false,
options: { authRequired: false },
},

View file

@ -15,6 +15,13 @@ export function defineVerifyRoute({ router, verificationCode }: RouteDefinitionP
router.post(
{
path: '/internal/interactive_setup/verify',
security: {
authz: {
enabled: false,
reason:
'Interactive setup is strictly a "pre-boot" feature which cannot leverage conventional authorization.',
},
},
validate: {
body: schema.object({
code: schema.string(),

View file

@ -31,6 +31,13 @@ export function defineRecordAnalyticsOnAuthTypeRoutes({
router.post(
{
path: '/internal/security/analytics/_record_auth_type',
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the scoped ES cluster client of the internal authentication service',
},
},
validate: {
body: schema.nullable(
schema.object({ signature: schema.string(), timestamp: schema.number() })

View file

@ -135,6 +135,13 @@ export function defineRecordViolations({ router, analyticsService }: RouteDefini
router.post(
{
path: '/internal/security/analytics/_record_violations',
security: {
authz: {
enabled: false,
reason:
'This route is used by browsers to report CSP and Permission Policy violations. These requests are sent without authentication per the browser spec.',
},
},
validate: {
/**
* Chrome supports CSP3 spec and sends an array of reports. Safari only sends a single

View file

@ -15,7 +15,17 @@ export function defineAnonymousAccessGetCapabilitiesRoutes({
getAnonymousAccessService,
}: RouteDefinitionParams) {
router.get(
{ path: '/internal/security/anonymous_access/capabilities', validate: false },
{
path: '/internal/security/anonymous_access/capabilities',
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the scoped ES cluster client of the anonymous access service',
},
},
validate: false,
},
async (_context, request, response) => {
const anonymousAccessService = getAnonymousAccessService();
return response.ok({ body: await anonymousAccessService.getCapabilities(request) });

View file

@ -18,7 +18,16 @@ export function defineAnonymousAccessGetStateRoutes({
getAnonymousAccessService,
}: RouteDefinitionParams) {
router.get(
{ path: '/internal/security/anonymous_access/state', validate: false },
{
path: '/internal/security/anonymous_access/state',
security: {
authz: {
enabled: false,
reason: 'This route is used for anonymous access',
},
},
validate: false,
},
async (_context, _request, response) => {
const anonymousAccessService = getAnonymousAccessService();
const accessURLParameters = anonymousAccessService.accessURLParameters

View file

@ -32,6 +32,13 @@ export function defineCreateApiKeyRoutes({
router.post(
{
path: '/internal/security/api_key',
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the scoped ES cluster client of the internal authentication service',
},
},
validate: {
body: schema.oneOf([
restApiKeySchema,

View file

@ -16,6 +16,13 @@ export function defineEnabledApiKeysRoutes({
router.get(
{
path: '/internal/security/api_key/_enabled',
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the scoped ES cluster client of the internal authentication service',
},
},
validate: false,
},
createLicensedRouteHandler(async (context, request, response) => {

View file

@ -22,6 +22,12 @@ export function defineHasApiKeysRoutes({
router.get(
{
path: '/internal/security/api_key/_has_active',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to the scoped ES cluster client of the internal authentication service, and to Core's ES client`,
},
},
validate: false,
options: {
access: 'internal',

View file

@ -21,6 +21,12 @@ export function defineInvalidateApiKeysRoutes({ router }: RouteDefinitionParams)
router.post(
{
path: '/internal/security/api_key/invalidate',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's ES client`,
},
},
validate: {
body: schema.object({
apiKeys: schema.arrayOf(schema.object({ id: schema.string(), name: schema.string() })),

View file

@ -25,6 +25,12 @@ export function defineQueryApiKeysAndAggregationsRoute({
// on behalf of the user making the request and governed by the user's own cluster privileges.
{
path: '/internal/security/api_key/_query',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to the scoped ES cluster client of the internal authentication service, and to Core's ES client`,
},
},
validate: {
body: schema.object({
query: schema.maybe(schema.object({}, { unknowns: 'allow' })),

View file

@ -34,6 +34,12 @@ export function defineUpdateApiKeyRoutes({
router.put(
{
path: '/internal/security/api_key',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to the scoped ES cluster client of the internal authentication service`,
},
},
validate: {
body: schema.oneOf([
updateRestApiKeySchema,

View file

@ -43,6 +43,12 @@ export function defineCommonRoutes({
router.get(
{
path,
security: {
authz: {
enabled: false,
reason: 'This route must remain accessible to 3rd-party IdPs',
},
},
// Allow unknown query parameters as this endpoint can be hit by the 3rd-party with any
// set of query string parameters (e.g. SAML/OIDC logout request/response parameters).
validate: { query: schema.object({}, { unknowns: 'allow' }) },
@ -92,7 +98,17 @@ export function defineCommonRoutes({
]) {
const deprecated = path === '/api/security/v1/me';
router.get(
{ path, validate: false, options: { access: deprecated ? 'public' : 'internal' } },
{
path,
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's security service; there must be an authenticated user for this route to return information`,
},
},
validate: false,
options: { access: deprecated ? 'public' : 'internal' },
},
createLicensedRouteHandler(async (context, request, response) => {
if (deprecated) {
logger.warn(
@ -135,10 +151,16 @@ export function defineCommonRoutes({
}
// Register the login route for serverless for the time being. Note: This route will move into the buildFlavor !== 'serverless' block below. See next line.
// ToDo: In the serverless environment, we do not support API login - the only valid authentication methodology (or maybe just method or mechanism?) is SAML
// ToDo: In the serverless environment, we do not support API login - the only valid authentication type is SAML
router.post(
{
path: '/internal/security/login',
security: {
authz: {
enabled: false,
reason: `This route provides basic and token login capbility, which is delegated to the internal authentication service`,
},
},
validate: {
body: schema.object({
providerType: schema.string(),
@ -183,7 +205,16 @@ export function defineCommonRoutes({
if (buildFlavor !== 'serverless') {
// In the serverless offering, the access agreement functionality isn't available.
router.post(
{ path: '/internal/security/access_agreement/acknowledge', validate: false },
{
path: '/internal/security/access_agreement/acknowledge',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to the internal authentication service; there must be an authenticated user for this route to function`,
},
},
validate: false,
},
createLicensedRouteHandler(async (context, request, response) => {
// If license doesn't allow access agreement we shouldn't handle request.
if (!license.getFeatures().allowAccessAgreement) {

View file

@ -87,6 +87,12 @@ export function defineOIDCRoutes({
router.get(
{
path,
security: {
authz: {
enabled: false,
reason: 'This route must remain accessible to 3rd-party OIDC providers',
},
},
validate: {
query: schema.object(
{
@ -176,6 +182,12 @@ export function defineOIDCRoutes({
router.post(
{
path,
security: {
authz: {
enabled: false,
reason: 'This route must remain accessible to 3rd-party OIDC providers',
},
},
validate: {
body: schema.object(
{
@ -221,6 +233,12 @@ export function defineOIDCRoutes({
router.get(
{
path: '/api/security/oidc/initiate_login',
security: {
authz: {
enabled: false,
reason: 'This route must remain accessible to 3rd-party OIDC providers',
},
},
validate: {
query: schema.object(
{

View file

@ -30,6 +30,12 @@ export function defineSAMLRoutes({
router.post(
{
path,
security: {
authz: {
enabled: false,
reason: 'This route must remain accessible to 3rd-party SAML providers',
},
},
validate: {
body: schema.object(
{ SAMLResponse: schema.string(), RelayState: schema.maybe(schema.string()) },

View file

@ -14,6 +14,13 @@ export function defineGetPrivilegesRoutes({ router, authz }: RouteDefinitionPara
router.get(
{
path: '/api/security/privileges',
security: {
authz: {
enabled: false,
reason:
'This route is opted out from authorization because it returns only the global list of Kibana privileges',
},
},
validate: {
query: schema.object({
// We don't use `schema.boolean` here, because all query string parameters are treated as

View file

@ -9,7 +9,16 @@ import type { RouteDefinitionParams } from '../..';
export function defineGetBuiltinPrivilegesRoutes({ router }: RouteDefinitionParams) {
router.get(
{ path: '/internal/security/esPrivileges/builtin', validate: false },
{
path: '/internal/security/esPrivileges/builtin',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: false,
},
async (context, request, response) => {
const esClient = (await context.core).elasticsearch.client;
const privileges = await esClient.asCurrentUser.security.getBuiltinPrivileges();

View file

@ -25,6 +25,12 @@ export function defineDeleteRolesRoutes({ router }: RouteDefinitionParams) {
.addVersion(
{
version: API_VERSIONS.roles.public.v1,
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: {
request: {
params: schema.object({ name: schema.string({ minLength: 1 }) }),

View file

@ -32,6 +32,12 @@ export function defineGetRolesRoutes({
.addVersion(
{
version: API_VERSIONS.roles.public.v1,
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: {
request: {
params: schema.object({

View file

@ -33,6 +33,12 @@ export function defineGetAllRolesRoutes({
.addVersion(
{
version: API_VERSIONS.roles.public.v1,
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: {
request: {
query: schema.maybe(

View file

@ -52,6 +52,12 @@ export function defineBulkCreateOrUpdateRolesRoutes({
.addVersion(
{
version: API_VERSIONS.roles.public.v1,
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: {
request: {
body: getBulkCreateOrUpdatePayloadSchema(() => {

View file

@ -35,6 +35,12 @@ export function definePutRolesRoutes({
.addVersion(
{
version: API_VERSIONS.roles.public.v1,
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: {
request: {
params: schema.object({

View file

@ -19,6 +19,12 @@ export function defineShareSavedObjectPermissionRoutes({
router.get(
{
path: '/internal/security/_share_saved_object_permissions',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to the internal authorization service's checkPrivilegesWithRequest function`,
},
},
validate: { query: schema.object({ type: schema.string() }) },
},
createLicensedRouteHandler(async (context, request, response) => {

View file

@ -23,6 +23,12 @@ export function defineKibanaUserRoleDeprecationRoutes({ router, logger }: RouteD
router.post(
{
path: '/internal/security/deprecations/kibana_user_role/_fix_users',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: false,
},
createLicensedRouteHandler(async (context, request, response) => {
@ -88,6 +94,12 @@ export function defineKibanaUserRoleDeprecationRoutes({ router, logger }: RouteD
router.post(
{
path: '/internal/security/deprecations/kibana_user_role/_fix_role_mappings',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: false,
},
createLicensedRouteHandler(async (context, request, response) => {

View file

@ -43,6 +43,12 @@ export function defineSecurityFeatureCheckRoute({ router, logger }: RouteDefinit
router.get(
{
path: '/internal/security/_check_security_features',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: false,
},
createLicensedRouteHandler(async (context, request, response) => {

View file

@ -14,6 +14,12 @@ export function defineGetFieldsRoutes({ router }: RouteDefinitionParams) {
router.get(
{
path: '/internal/security/fields/{query}',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: { params: schema.object({ query: schema.string() }) },
},
async (context, request, response) => {

View file

@ -15,6 +15,12 @@ export function defineRoleMappingDeleteRoutes({ router }: RouteDefinitionParams)
router.delete(
{
path: '/internal/security/role_mapping/{name}',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: {
params: schema.object({
name: schema.string(),

View file

@ -18,6 +18,12 @@ export function defineRoleMappingGetRoutes(params: RouteDefinitionParams) {
router.get(
{
path: '/internal/security/role_mapping/{name?}',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: {
params: schema.object({
name: schema.maybe(schema.string()),

View file

@ -15,6 +15,12 @@ export function defineRoleMappingPostRoutes({ router }: RouteDefinitionParams) {
router.post(
{
path: '/internal/security/role_mapping/{name}',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: {
params: schema.object({
name: schema.string(),

View file

@ -29,7 +29,16 @@ export function defineSecurityCheckupGetStateRoutes({
const doesClusterHaveUserData = createClusterDataCheck();
router.get(
{ path: '/internal/security/security_checkup/state', validate: false },
{
path: '/internal/security/security_checkup/state',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: false,
},
async (context, _request, response) => {
const esClient = (await context.core).elasticsearch.client;
let displayAlert = false;

View file

@ -14,6 +14,13 @@ export function defineSessionExtendRoutes({ router, basePath }: RouteDefinitionP
router.post(
{
path: '/internal/security/session',
security: {
authz: {
enabled: false,
reason:
'This route is opted out from authorization because it only redirects to the /internal/security/session endpoint',
},
},
validate: false,
},
async (_context, _request, response) => {

View file

@ -14,7 +14,17 @@ import type { SessionInfo } from '../../../common/types';
*/
export function defineSessionInfoRoutes({ router, getSession }: RouteDefinitionParams) {
router.get(
{ path: '/internal/security/session', validate: false },
{
path: '/internal/security/session',
security: {
authz: {
enabled: false,
reason:
'This route is opted out from authorization because a valid session is required, and it does not return sensative session information',
},
},
validate: false,
},
async (_context, request, response) => {
const { value: sessionValue } = await getSession().get(request);
if (sessionValue) {

View file

@ -20,6 +20,13 @@ export function defineGetCurrentUserProfileRoute({
router.get(
{
path: '/internal/security/user_profile',
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the internal authorization service; a currently authenticated user is required',
},
},
validate: {
query: schema.object({ dataPath: schema.maybe(schema.string()) }),
},

View file

@ -27,6 +27,13 @@ export function defineUpdateUserProfileDataRoute({
router.post(
{
path: '/internal/security/user_profile/_data',
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the internal authorization service; an authenticated user and valid session are required',
},
},
validate: {
body: schema.recordOf(schema.string(), schema.any()),
},

View file

@ -24,6 +24,12 @@ export function defineChangeUserPasswordRoutes({
router.post(
{
path: '/internal/security/users/{username}/password',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to the internal authorization service and the Security plugin's canUserChangePassword function`,
},
},
validate: {
params: schema.object({ username: schema.string({ minLength: 1, maxLength: 1024 }) }),
body: schema.object({

View file

@ -15,6 +15,12 @@ export function defineCreateOrUpdateUserRoutes({ router }: RouteDefinitionParams
router.post(
{
path: '/internal/security/users/{username}',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: {
params: schema.object({ username: schema.string({ minLength: 1, maxLength: 1024 }) }),
body: schema.object({

View file

@ -15,6 +15,12 @@ export function defineDeleteUserRoutes({ router }: RouteDefinitionParams) {
router.delete(
{
path: '/internal/security/users/{username}',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: {
params: schema.object({ username: schema.string({ minLength: 1, maxLength: 1024 }) }),
},

View file

@ -15,6 +15,12 @@ export function defineDisableUserRoutes({ router }: RouteDefinitionParams) {
router.post(
{
path: '/internal/security/users/{username}/_disable',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: {
params: schema.object({ username: schema.string({ minLength: 1, maxLength: 1024 }) }),
},

View file

@ -15,6 +15,12 @@ export function defineEnableUserRoutes({ router }: RouteDefinitionParams) {
router.post(
{
path: '/internal/security/users/{username}/_enable',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: {
params: schema.object({ username: schema.string({ minLength: 1, maxLength: 1024 }) }),
},

View file

@ -15,6 +15,12 @@ export function defineGetUserRoutes({ router }: RouteDefinitionParams) {
router.get(
{
path: '/internal/security/users/{username}',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: {
params: schema.object({ username: schema.string({ minLength: 1, maxLength: 1024 }) }),
},

View file

@ -11,7 +11,16 @@ import { createLicensedRouteHandler } from '../licensed_route_handler';
export function defineGetAllUsersRoutes({ router }: RouteDefinitionParams) {
router.get(
{ path: '/internal/security/users', validate: false },
{
path: '/internal/security/users',
security: {
authz: {
enabled: false,
reason: `This route delegates authorization to Core's scoped ES cluster client`,
},
},
validate: false,
},
createLicensedRouteHandler(async (context, request, response) => {
try {
const esClient = (await context.core).elasticsearch.client;

View file

@ -35,7 +35,17 @@ export function defineAccessAgreementRoutes({
);
router.get(
{ path: '/internal/security/access_agreement/state', validate: false },
{
path: '/internal/security/access_agreement/state',
security: {
authz: {
enabled: false,
reason:
'This route is opted out from authorization because it requires only an active session in order to function',
},
},
validate: false,
},
createLicensedRouteHandler(async (context, request, response) => {
if (!canHandleRequest()) {
return response.forbidden({

View file

@ -57,7 +57,18 @@ export function defineLoginRoutes({
);
router.get(
{ path: '/internal/security/login_state', validate: false, options: { authRequired: false } },
{
path: '/internal/security/login_state',
security: {
authz: {
enabled: false,
reason:
'This route is opted out from authorization because it only provides non-sensative information about authentication provider configuration',
},
},
validate: false,
options: { authRequired: false },
},
async (context, request, response) => {
const { allowLogin, layout = 'form' } = license.getFeatures();
const { sortedProviders, selector } = config.authc;

View file

@ -49,9 +49,21 @@ describe.skip('onPostAuthInterceptor', () => {
*/
function initKbnServer(router: IRouter, basePath: IBasePath) {
router.get({ path: '/api/np_test/foo', validate: false }, (context, req, h) => {
return h.ok({ body: { path: req.url.pathname, basePath: basePath.get(req) } });
});
router.get(
{
path: '/api/np_test/foo',
security: {
authz: {
enabled: false,
reason: 'This route is opted out from authorization',
},
},
validate: false,
},
(context, req, h) => {
return h.ok({ body: { path: req.url.pathname, basePath: basePath.get(req) } });
}
);
}
async function request(

View file

@ -38,14 +38,32 @@ describe.skip('onRequestInterceptor', () => {
function initKbnServer(router: IRouter, basePath: IBasePath) {
router.get(
{ path: '/np_foo', validate: false },
{
path: '/np_foo',
security: {
authz: {
enabled: false,
reason: 'This route is opted out from authorization',
},
},
validate: false,
},
(context: unknown, req: KibanaRequest, h: KibanaResponseFactory) => {
return h.ok({ body: { path: req.url.pathname, basePath: basePath.get(req) } });
}
);
router.get(
{ path: '/some/path/s/np_foo/bar', validate: false },
{
path: '/some/path/s/np_foo/bar',
security: {
authz: {
enabled: false,
reason: 'This route is opted out from authorization',
},
},
validate: false,
},
(context: unknown, req: KibanaRequest, h: KibanaResponseFactory) => {
return h.ok({ body: { path: req.url.pathname, basePath: basePath.get(req) } });
}
@ -54,6 +72,12 @@ describe.skip('onRequestInterceptor', () => {
router.get(
{
path: '/i/love/np_spaces',
security: {
authz: {
enabled: false,
reason: 'This route is opted out from authorization',
},
},
validate: {
query: schema.object({
queryParam: schema.string({

View file

@ -31,6 +31,13 @@ export function initDeleteSpacesApi(deps: ExternalRouteDeps) {
.addVersion(
{
version: API_VERSIONS.public.v1,
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the spaces service via a scoped spaces client',
},
},
validate: {
request: {
params: schema.object({

View file

@ -18,6 +18,13 @@ export function initDisableLegacyUrlAliasesApi(deps: ExternalRouteDeps) {
router.post(
{
path: '/api/spaces/_disable_legacy_url_aliases',
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the spaces service via a scoped spaces client',
},
},
options: {
access: isServerless ? 'internal' : 'public',
summary: 'Disable legacy URL aliases',

View file

@ -28,6 +28,13 @@ export function initGetSpaceApi(deps: ExternalRouteDeps) {
.addVersion(
{
version: API_VERSIONS.public.v1,
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the spaces service via a scoped spaces client',
},
},
validate: {
request: {
params: schema.object({

View file

@ -27,6 +27,13 @@ export function initGetAllSpacesApi(deps: ExternalRouteDeps) {
.addVersion(
{
version: API_VERSIONS.public.v1,
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the spaces service via a scoped spaces client',
},
},
validate: {
request: {
query: schema.object({

View file

@ -17,6 +17,13 @@ export function initGetShareableReferencesApi(deps: ExternalRouteDeps) {
router.post(
{
path: '/api/spaces/_get_shareable_references',
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the spaces service via a scoped spaces client',
},
},
options: {
access: isServerless ? 'internal' : 'public',
summary: `Get shareable references`,

View file

@ -30,6 +30,13 @@ export function initPostSpacesApi(deps: ExternalRouteDeps) {
.addVersion(
{
version: API_VERSIONS.public.v1,
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the spaces service via a scoped spaces client',
},
},
validate: {
request: {
body: getSpaceSchema(isServerless),

View file

@ -29,6 +29,13 @@ export function initPutSpacesApi(deps: ExternalRouteDeps) {
.addVersion(
{
version: API_VERSIONS.public.v1,
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the spaces service via a scoped spaces client',
},
},
validate: {
request: {
params: schema.object({

View file

@ -40,6 +40,13 @@ export function initUpdateObjectsSpacesApi(deps: ExternalRouteDeps) {
router.post(
{
path: '/api/spaces/_update_objects_spaces',
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the spaces service via a scoped spaces client',
},
},
options: {
access: isServerless ? 'internal' : 'public',
summary: `Update saved objects in spaces`,

View file

@ -15,6 +15,13 @@ export function initGetActiveSpaceApi(deps: InternalRouteDeps) {
router.get(
{
path: '/internal/spaces/_active_space',
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the spaces service getActiveSpace API, which uses a scoped spaces client',
},
},
validate: false,
},
createLicensedRouteHandler(async (context, request, response) => {

View file

@ -37,6 +37,13 @@ export function initSetSolutionSpaceApi(deps: InternalRouteDeps) {
router.put(
{
path: '/internal/spaces/space/{id}/solution',
security: {
authz: {
enabled: false,
reason:
'This route delegates authorization to the spaces service via a scoped spaces client',
},
},
options: {
description: `Update solution for a space`,
},