mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Unauthorized route migration for routes owned by kibana-core (#198333)
### 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: Jean-Louis Leysens <jeanlouis.leysens@elastic.co>
This commit is contained in:
parent
9bb3661060
commit
763b5deafd
20 changed files with 281 additions and 25 deletions
|
@ -14,6 +14,12 @@ export const registerHitsStatusRoute = (router: IRouter) => {
|
|||
router.post(
|
||||
{
|
||||
path: '/api/home/hits_status',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: {
|
||||
body: schema.object({
|
||||
index: schema.string(),
|
||||
|
|
|
@ -15,6 +15,12 @@ export const registerBulkDeleteRoute = (router: IRouter) => {
|
|||
router.post(
|
||||
{
|
||||
path: '/internal/kibana/management/saved_objects/_bulk_delete',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: {
|
||||
body: schema.arrayOf(
|
||||
schema.object({
|
||||
|
|
|
@ -20,6 +20,12 @@ export const registerBulkGetRoute = (
|
|||
router.post(
|
||||
{
|
||||
path: '/api/kibana/management/saved_objects/_bulk_get',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: {
|
||||
body: schema.arrayOf(
|
||||
schema.object({
|
||||
|
|
|
@ -34,6 +34,12 @@ export const registerFindRoute = (
|
|||
router.get(
|
||||
{
|
||||
path: '/api/kibana/management/saved_objects/_find',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: {
|
||||
query: schema.object({
|
||||
perPage: schema.number({ min: 0, defaultValue: 20 }),
|
||||
|
|
|
@ -23,6 +23,12 @@ export const registerGetAllowedTypesRoute = (router: IRouter) => {
|
|||
router.get(
|
||||
{
|
||||
path: '/api/kibana/management/saved_objects/_allowed_types',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: false,
|
||||
},
|
||||
async (context, req, res) => {
|
||||
|
|
|
@ -21,6 +21,12 @@ export const registerRelationshipsRoute = (
|
|||
router.get(
|
||||
{
|
||||
path: '/api/kibana/management/saved_objects/relationships/{type}/{id}',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: {
|
||||
params: schema.object({
|
||||
type: schema.string(),
|
||||
|
|
|
@ -17,6 +17,12 @@ export const registerScrollForCountRoute = (router: IRouter) => {
|
|||
router.post(
|
||||
{
|
||||
path: '/api/kibana/management/saved_objects/scroll/counts',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: {
|
||||
body: schema.object({
|
||||
typesToInclude: schema.arrayOf(schema.string()),
|
||||
|
|
|
@ -102,12 +102,46 @@ export function registerTelemetryConfigRoutes({
|
|||
options: { authRequired: 'optional' },
|
||||
})
|
||||
// Just because it used to be /v2/, we are creating identical v1 and v2.
|
||||
.addVersion({ version: '1', validate: v2Validations }, v2Handler)
|
||||
.addVersion({ version: '2', validate: v2Validations }, v2Handler);
|
||||
.addVersion(
|
||||
{
|
||||
version: '1',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: v2Validations,
|
||||
},
|
||||
v2Handler
|
||||
)
|
||||
.addVersion(
|
||||
{
|
||||
version: '2',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: v2Validations,
|
||||
},
|
||||
v2Handler
|
||||
);
|
||||
|
||||
// Register the deprecated public and path-based for BWC
|
||||
// as we know this one is used by other Elastic products to fetch the opt-in status.
|
||||
router.versioned
|
||||
.get({ access: 'public', path: FetchTelemetryConfigRoutePathBasedV2 })
|
||||
.addVersion({ version: '2023-10-31', validate: v2Validations }, v2Handler);
|
||||
router.versioned.get({ access: 'public', path: FetchTelemetryConfigRoutePathBasedV2 }).addVersion(
|
||||
{
|
||||
version: '2023-10-31',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: v2Validations,
|
||||
},
|
||||
v2Handler
|
||||
);
|
||||
}
|
||||
|
|
|
@ -40,8 +40,32 @@ export function registerTelemetryLastReported(
|
|||
router.versioned
|
||||
.get({ access: 'internal', path: LastReportedRoute })
|
||||
// Just because it used to be /v2/, we are creating identical v1 and v2.
|
||||
.addVersion({ version: '1', validate: v2GetValidations }, v2GetHandler)
|
||||
.addVersion({ version: '2', validate: v2GetValidations }, v2GetHandler);
|
||||
.addVersion(
|
||||
{
|
||||
version: '1',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: v2GetValidations,
|
||||
},
|
||||
v2GetHandler
|
||||
)
|
||||
.addVersion(
|
||||
{
|
||||
version: '2',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: v2GetValidations,
|
||||
},
|
||||
v2GetHandler
|
||||
);
|
||||
|
||||
// PUT to update
|
||||
const v2PutHandler: RequestHandler = async (context, req, res) => {
|
||||
|
@ -55,6 +79,30 @@ export function registerTelemetryLastReported(
|
|||
router.versioned
|
||||
.put({ access: 'internal', path: LastReportedRoute })
|
||||
// Just because it used to be /v2/, we are creating identical v1 and v2.
|
||||
.addVersion({ version: '1', validate: false }, v2PutHandler)
|
||||
.addVersion({ version: '2', validate: false }, v2PutHandler);
|
||||
.addVersion(
|
||||
{
|
||||
version: '1',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: false,
|
||||
},
|
||||
v2PutHandler
|
||||
)
|
||||
.addVersion(
|
||||
{
|
||||
version: '2',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: false,
|
||||
},
|
||||
v2PutHandler
|
||||
);
|
||||
}
|
||||
|
|
|
@ -128,6 +128,30 @@ export function registerTelemetryOptInRoutes({
|
|||
router.versioned
|
||||
.post({ access: 'internal', path: OptInRoute })
|
||||
// Just because it used to be /v2/, we are creating identical v1 and v2.
|
||||
.addVersion({ version: '1', validate: v2Validations }, v2Handler)
|
||||
.addVersion({ version: '2', validate: v2Validations }, v2Handler);
|
||||
.addVersion(
|
||||
{
|
||||
version: '1',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: v2Validations,
|
||||
},
|
||||
v2Handler
|
||||
)
|
||||
.addVersion(
|
||||
{
|
||||
version: '2',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: v2Validations,
|
||||
},
|
||||
v2Handler
|
||||
);
|
||||
}
|
||||
|
|
|
@ -72,6 +72,12 @@ export function registerTelemetryOptInStatsRoutes(
|
|||
.addVersion(
|
||||
{
|
||||
version: '2023-10-31',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: {
|
||||
request: {
|
||||
body: schema.object({
|
||||
|
|
|
@ -97,6 +97,30 @@ export function registerTelemetryUsageStatsRoutes(
|
|||
enableQueryVersion: true, // Allow specifying the version through querystring so that we can use it in Dev Console
|
||||
})
|
||||
// Just because it used to be /v2/, we are creating identical v1 and v2.
|
||||
.addVersion({ version: '1', validate: v2Validations }, v2Handler)
|
||||
.addVersion({ version: '2', validate: v2Validations }, v2Handler);
|
||||
.addVersion(
|
||||
{
|
||||
version: '1',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: v2Validations,
|
||||
},
|
||||
v2Handler
|
||||
)
|
||||
.addVersion(
|
||||
{
|
||||
version: '2',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: v2Validations,
|
||||
},
|
||||
v2Handler
|
||||
);
|
||||
}
|
||||
|
|
|
@ -56,6 +56,30 @@ export function registerTelemetryUserHasSeenNotice(router: IRouter, currentKiban
|
|||
router.versioned
|
||||
.put({ access: 'internal', path: UserHasSeenNoticeRoute })
|
||||
// Just because it used to be /v2/, we are creating identical v1 and v2.
|
||||
.addVersion({ version: '1', validate: false }, v2Handler)
|
||||
.addVersion({ version: '2', validate: false }, v2Handler);
|
||||
.addVersion(
|
||||
{
|
||||
version: '1',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: false,
|
||||
},
|
||||
v2Handler
|
||||
)
|
||||
.addVersion(
|
||||
{
|
||||
version: '2',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: false,
|
||||
},
|
||||
v2Handler
|
||||
);
|
||||
}
|
||||
|
|
|
@ -54,6 +54,12 @@ export function registerStatsRoute({
|
|||
router.get(
|
||||
{
|
||||
path: '/api/stats',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
options: {
|
||||
authRequired: !config.allowAnonymous,
|
||||
// The `api` tag ensures that unauthenticated calls receive a 401 rather than a 302 redirect to login page.
|
||||
|
|
|
@ -21,6 +21,12 @@ export function registerUiCountersRoute(
|
|||
router.post(
|
||||
{
|
||||
path: '/api/ui_counters/_report',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: {
|
||||
body: schema.object({
|
||||
report: reportSchema,
|
||||
|
|
|
@ -24,12 +24,24 @@ export function defineRoutes({
|
|||
path: ELASTICSEARCH_CONFIG_ROUTE,
|
||||
access: 'internal',
|
||||
})
|
||||
.addVersion({ version: '1', validate: {} }, async (context, request, response) => {
|
||||
const body: ElasticsearchConfigType = {
|
||||
elasticsearch_url: elasticsearchUrl,
|
||||
};
|
||||
return response.ok({
|
||||
body,
|
||||
});
|
||||
});
|
||||
.addVersion(
|
||||
{
|
||||
version: '1',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: {},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const body: ElasticsearchConfigType = {
|
||||
elasticsearch_url: elasticsearchUrl,
|
||||
};
|
||||
return response.ok({
|
||||
body,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,16 @@ export function registerFeatureUsageRoute(
|
|||
getStartServices: StartServicesAccessor<{}, LicensingPluginStart>
|
||||
) {
|
||||
router.get(
|
||||
{ path: '/api/licensing/feature_usage', validate: false },
|
||||
{
|
||||
path: '/api/licensing/feature_usage',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: false,
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const [, , { featureUsage }] = await getStartServices();
|
||||
return response.ok({
|
||||
|
|
|
@ -9,7 +9,16 @@ import { LicensingRouter } from '../types';
|
|||
|
||||
export function registerInfoRoute(router: LicensingRouter) {
|
||||
router.get(
|
||||
{ path: '/api/licensing/info', validate: false },
|
||||
{
|
||||
path: '/api/licensing/info',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: false,
|
||||
},
|
||||
async (context, request, response) => {
|
||||
return response.ok({
|
||||
body: (await context.licensing).license,
|
||||
|
|
|
@ -12,6 +12,12 @@ export function registerNotifyFeatureUsageRoute(router: LicensingRouter) {
|
|||
router.post(
|
||||
{
|
||||
path: '/internal/licensing/feature_usage/notify',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: {
|
||||
body: schema.object({
|
||||
featureName: schema.string(),
|
||||
|
|
|
@ -17,6 +17,12 @@ export function registerRegisterFeatureRoute(
|
|||
router.post(
|
||||
{
|
||||
path: '/internal/licensing/feature_usage/register',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route is opted out from authorization',
|
||||
},
|
||||
},
|
||||
validate: {
|
||||
body: schema.arrayOf(
|
||||
schema.object({
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue