mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Authz] Migrated routes with access tags to security config (#209756)
## Summary This PR migrates the last routes with `access:<privilege>` tags used in route definitions to 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:** Access control tags were defined in the `options` object of the route: ```ts router.get({ path: '/api/path', options: { tags: ['access:<privilege_1>', 'access:<privilege_2>'], }, ... }, handler); ``` ### **After Migration:** Tags have been replaced with the more robust `security.authz.requiredPrivileges` field under `security`: ```ts router.get({ path: '/api/path', security: { authz: { requiredPrivileges: ['<privilege_1>', '<privilege_2>'], }, }, ... }, handler); ``` ### Checklist - [x] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
9bdee77409
commit
ad0e1d9d9d
16 changed files with 67 additions and 40 deletions
|
@ -69,8 +69,10 @@ export class FeatureControlsPluginExample
|
|||
{
|
||||
path: '/internal/my_plugin/sensitive_action',
|
||||
validate: false,
|
||||
options: {
|
||||
tags: ['access:my_closed_example_api'],
|
||||
security: {
|
||||
authz: {
|
||||
requiredPrivileges: ['my_closed_example_api'],
|
||||
},
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
|
|
|
@ -40,7 +40,11 @@ export class UserProfilesPlugin implements Plugin<void, void, SetupDeps, StartDe
|
|||
/**
|
||||
* Important: You must restrict access to this endpoint using access `tags`.
|
||||
*/
|
||||
options: { tags: ['access:suggestUserProfiles'] },
|
||||
security: {
|
||||
authz: {
|
||||
requiredPrivileges: ['suggestUserProfiles'],
|
||||
},
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const [, pluginDeps] = await core.getStartServices();
|
||||
|
|
|
@ -268,9 +268,11 @@ export const createEntityRoute = (router: Router): void => {
|
|||
.post({
|
||||
access: 'public',
|
||||
path: '/api/my/data/{id}',
|
||||
options: {
|
||||
tags: ['access:securitySolution'],
|
||||
},
|
||||
security: {
|
||||
authz: {
|
||||
requiredPrivileges: ['securitySolution']
|
||||
}
|
||||
}
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
|
|
|
@ -93,8 +93,10 @@ describe('CoreApp', () => {
|
|||
expect(routerMock.versioned.put).toHaveBeenCalledWith({
|
||||
path: '/internal/core/_settings',
|
||||
access: 'internal',
|
||||
options: {
|
||||
tags: ['access:updateDynamicConfig'],
|
||||
security: {
|
||||
authz: {
|
||||
requiredPrivileges: ['updateDynamicConfig'],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -279,8 +279,10 @@ export class CoreAppsService {
|
|||
.put({
|
||||
path: '/internal/core/_settings',
|
||||
access: 'internal',
|
||||
options: {
|
||||
tags: ['access:updateDynamicConfig'],
|
||||
security: {
|
||||
authz: {
|
||||
requiredPrivileges: ['updateDynamicConfig'],
|
||||
},
|
||||
},
|
||||
})
|
||||
.addVersion(
|
||||
|
|
|
@ -87,13 +87,9 @@ export const registerAutocompleteEntitiesRoute = (deps: RouteDependencies) => {
|
|||
deps.router.get(
|
||||
{
|
||||
path: '/api/console/autocomplete_entities',
|
||||
options: {
|
||||
tags: ['access:console'],
|
||||
},
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'Relies on es client for authorization',
|
||||
requiredPrivileges: ['console'],
|
||||
},
|
||||
},
|
||||
validate: autoCompleteEntitiesValidationConfig,
|
||||
|
|
|
@ -46,7 +46,7 @@ export function registerTelemetryUsageStatsRoutes(
|
|||
const security = getSecurity();
|
||||
// We need to check useRbacForRequest to figure out if ES has security enabled before making the privileges check
|
||||
if (security && unencrypted && security.authz.mode.useRbacForRequest(req)) {
|
||||
// Normally we would use `options: { tags: ['access:decryptedTelemetry'] }` in the route definition to check authorization for an
|
||||
// Normally we would use `security: { authz: { requiredPrivileges: ['decryptedTelemetry'] } } }` in the route definition to check authorization for an
|
||||
// API action, however, we want to check this conditionally based on the `unencrypted` parameter. In this case we need to use the
|
||||
// security API directly to check privileges for this action. Note that the 'decryptedTelemetry' API privilege string is only
|
||||
// granted to users that have "Global All" or "Global Read" privileges in Kibana.
|
||||
|
|
|
@ -122,8 +122,10 @@ export function routes(coreSetup: CoreSetup<StartDeps, unknown>, logger: Logger)
|
|||
.post({
|
||||
path: '/internal/data_visualizer/inference/{inferenceId}',
|
||||
access: 'internal',
|
||||
options: {
|
||||
tags: ['access:fileUpload:analyzeFile'],
|
||||
security: {
|
||||
authz: {
|
||||
requiredPrivileges: ['fileUpload:analyzeFile'],
|
||||
},
|
||||
},
|
||||
})
|
||||
.addVersion(
|
||||
|
|
|
@ -54,25 +54,27 @@ export interface FeatureKibanaPrivileges {
|
|||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Configure your routes with a tag starting with the 'access:' prefix
|
||||
* // Configure your routes with requiredPrivileges
|
||||
* server.route({
|
||||
* path: '/api/my-route',
|
||||
* method: 'GET',
|
||||
* handler: () => { ...},
|
||||
* options: {
|
||||
* tags: ['access:my_feature-admin']
|
||||
* }
|
||||
* security: {
|
||||
* authz: {
|
||||
* requiredPrivileges: ['my_feature_admin']
|
||||
* },
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* Then, specify the tags here (without the 'access:' prefix) which should be secured:
|
||||
* Then, specify requiredPrivileges which should be secured:
|
||||
*
|
||||
* {
|
||||
* api: ['my_feature-admin']
|
||||
* api: ['my_feature_admin']
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* NOTE: It is important to name your tags in a way that will not collide with other platform/plugins/shared/features.
|
||||
* A generic tag name like "access:read" could be used elsewhere, and access to that API endpoint would also
|
||||
* NOTE: It is important to name your privileges in a way that will not collide with other platform/plugins/shared/features.
|
||||
* A generic tag name like "read" could be used elsewhere, and access to that API endpoint would also
|
||||
* extend to any routes you have also tagged with that name.
|
||||
*/
|
||||
api?: readonly string[];
|
||||
|
|
|
@ -119,7 +119,11 @@ export function backgroundTaskUtilizationRoute(
|
|||
},
|
||||
},
|
||||
// Uncomment when we determine that we can restrict API usage to Global admins based on telemetry
|
||||
// options: { tags: ['access:taskManager'] },
|
||||
// security: {
|
||||
// authz: {
|
||||
// requiredPrivileges: ['taskManager'],
|
||||
// },
|
||||
// },
|
||||
validate: false,
|
||||
options: {
|
||||
access: 'public', // access must be public to allow "system" users, like metrics collectors, to access these routes
|
||||
|
|
|
@ -148,7 +148,11 @@ export function healthRoute(params: HealthRouteParams): {
|
|||
},
|
||||
},
|
||||
// Uncomment when we determine that we can restrict API usage to Global admins based on telemetry
|
||||
// options: { tags: ['access:taskManager'] },
|
||||
// security: {
|
||||
// authz: {
|
||||
// requiredPrivileges: ['taskManager'],
|
||||
// },
|
||||
// },
|
||||
validate: false,
|
||||
options: {
|
||||
access: 'public',
|
||||
|
|
|
@ -62,7 +62,11 @@ export function metricsRoute(params: MetricsRouteParams) {
|
|||
tags: ['security:acceptJWT'],
|
||||
},
|
||||
// Uncomment when we determine that we can restrict API usage to Global admins based on telemetry
|
||||
// options: { tags: ['access:taskManager'] },
|
||||
// security: {
|
||||
// authz: {
|
||||
// requiredPrivileges: ['taskManager'],
|
||||
// },
|
||||
// },
|
||||
validate: {
|
||||
query: QuerySchema,
|
||||
},
|
||||
|
|
|
@ -9,8 +9,10 @@ import { extractEntityIndexPatternsFromDefinitions } from './extract_entity_inde
|
|||
|
||||
export const getEntityDefinitionSourceIndexPatternsByType = createInventoryServerRoute({
|
||||
endpoint: 'GET /internal/inventory/entity/definitions/sources',
|
||||
options: {
|
||||
tags: ['access:inventory'],
|
||||
security: {
|
||||
authz: {
|
||||
requiredPrivileges: ['inventory'],
|
||||
},
|
||||
},
|
||||
async handler({ context, request, plugins }) {
|
||||
const [_coreContext, entityManagerStart] = await Promise.all([
|
||||
|
|
|
@ -44,15 +44,12 @@ export class KibanaFramework {
|
|||
config: InfraRouteConfig<Params, Query, Body, Method>,
|
||||
handler: RequestHandler<Params, Query, Body, RequestHandlerContext>
|
||||
) {
|
||||
const defaultOptions = {
|
||||
tags: ['access:infra'],
|
||||
};
|
||||
const routeConfig = {
|
||||
path: config.path,
|
||||
validate: config.validate,
|
||||
// Currently we have no use of custom options beyond tags, this can be extended
|
||||
// beyond defaultOptions if it's needed.
|
||||
options: defaultOptions,
|
||||
security: {
|
||||
authz: { requiredPrivileges: ['infra'] },
|
||||
},
|
||||
};
|
||||
switch (config.method) {
|
||||
case 'get':
|
||||
|
|
|
@ -124,11 +124,13 @@ export const bulkDeleteRulesRoute = (
|
|||
access: 'public',
|
||||
path: DETECTION_ENGINE_RULES_BULK_DELETE,
|
||||
options: {
|
||||
tags: ['access:securitySolution'],
|
||||
timeout: {
|
||||
idleSocket: RULE_MANAGEMENT_BULK_ACTION_SOCKET_TIMEOUT_MS,
|
||||
},
|
||||
},
|
||||
security: {
|
||||
authz: { requiredPrivileges: ['securitySolution'] },
|
||||
},
|
||||
};
|
||||
router.versioned.delete(routeConfig).addVersion(
|
||||
{
|
||||
|
|
|
@ -25,8 +25,10 @@ export const entityStoreInternalPrivilegesRoute = (
|
|||
.get({
|
||||
access: 'internal',
|
||||
path: ENTITY_STORE_INTERNAL_PRIVILEGES_URL,
|
||||
options: {
|
||||
tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`],
|
||||
security: {
|
||||
authz: {
|
||||
requiredPrivileges: ['securitySolution', `${APP_ID}-entity-analytics`],
|
||||
},
|
||||
},
|
||||
})
|
||||
.addVersion(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue