Skip to content

Commit

Permalink
Unauthorized route migration for routes owned by kibana-core (elastic…
Browse files Browse the repository at this point in the history
…#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 <[email protected]>
  • Loading branch information
kibanamachine and jloleysens authored Nov 12, 2024
1 parent 9bb3661 commit 763b5de
Show file tree
Hide file tree
Showing 20 changed files with 281 additions and 25 deletions.
6 changes: 6 additions & 0 deletions src/plugins/home/server/routes/fetch_es_hits_status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
6 changes: 6 additions & 0 deletions src/plugins/saved_objects_management/server/routes/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
Expand Down
44 changes: 39 additions & 5 deletions src/plugins/telemetry/server/routes/telemetry_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
}
56 changes: 52 additions & 4 deletions src/plugins/telemetry/server/routes/telemetry_last_reported.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand All @@ -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
);
}
28 changes: 26 additions & 2 deletions src/plugins/telemetry/server/routes/telemetry_opt_in.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
}
6 changes: 6 additions & 0 deletions src/plugins/telemetry/server/routes/telemetry_opt_in_stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
28 changes: 26 additions & 2 deletions src/plugins/telemetry/server/routes/telemetry_usage_stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
}
6 changes: 6 additions & 0 deletions src/plugins/usage_collection/server/routes/stats/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 6 additions & 0 deletions src/plugins/usage_collection/server/routes/ui_counters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
28 changes: 20 additions & 8 deletions x-pack/plugins/cloud/server/routes/elasticsearch_routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
}
);
}
11 changes: 10 additions & 1 deletion x-pack/plugins/licensing/server/routes/feature_usage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
Loading

0 comments on commit 763b5de

Please sign in to comment.