From 551257f7ba2a2d5ea71bc212c46953d906ad94f9 Mon Sep 17 00:00:00 2001 From: Jeramy Soucy Date: Mon, 16 May 2022 17:52:05 +0200 Subject: [PATCH] [7.17] Resolves UI Breaks from Malformed Roles (#131915) (#132149) * Resolves UI Breaks from Malformed Roles (#131915) * Adds catch of exceptions from PrivilegeSerializer deserialize methods to role transform function. Resolves 124808 where malformed Elasticsearch roles cause Kibana users and roles UIs to not display correctly. * Adds logger to role transform functions * File accidentally not saved prior to last commit (cherry picked from commit f4eb311f6a4e261830ce6b74b1804aaf33bfad58) # Conflicts: # x-pack/plugins/security/server/authorization/roles/elasticsearch_role.test.ts # x-pack/plugins/security/server/authorization/roles/elasticsearch_role.ts # x-pack/plugins/security/server/routes/authorization/roles/get.ts # x-pack/plugins/security/server/routes/authorization/roles/get_all.ts * Fixed import and test issues. --- .../authorization/roles/elasticsearch_role.ts | 31 ++++++++++++++----- .../deprecations/privilege_deprecations.ts | 3 +- .../server/routes/authorization/roles/get.ts | 5 +-- .../routes/authorization/roles/get_all.ts | 5 +-- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/security/server/authorization/roles/elasticsearch_role.ts b/x-pack/plugins/security/server/authorization/roles/elasticsearch_role.ts index c0dab16f97af8..8909213da70c9 100644 --- a/x-pack/plugins/security/server/authorization/roles/elasticsearch_role.ts +++ b/x-pack/plugins/security/server/authorization/roles/elasticsearch_role.ts @@ -5,11 +5,13 @@ * 2.0. */ +import type { Logger } from '../../../../../../src/core/server'; import { GLOBAL_RESOURCE, RESERVED_PRIVILEGES_APPLICATION_WILDCARD, } from '../../../common/constants'; import type { Role, RoleKibanaPrivilege } from '../../../common/model'; +import { getDetailedErrorMessage } from '../../errors'; import { PrivilegeSerializer } from '../privilege_serializer'; import { ResourceSerializer } from '../resource_serializer'; @@ -27,11 +29,13 @@ export type ElasticsearchRole = Pick, name: string, - application: string + application: string, + logger: Logger ): Role { const kibanaTransformResult = transformRoleApplicationsToKibanaPrivileges( elasticsearchRole.applications, - application + application, + logger ); return { @@ -54,7 +58,8 @@ export function transformElasticsearchRoleToRole( function transformRoleApplicationsToKibanaPrivileges( roleApplications: ElasticsearchRole['applications'], - application: string + application: string, + logger: Logger ) { const roleKibanaApplications = roleApplications.filter( (roleApplication) => @@ -184,9 +189,9 @@ function transformRoleApplicationsToKibanaPrivileges( }; } - return { - success: true, - value: roleKibanaApplications.map(({ resources, privileges }) => { + // try/catch block ensures graceful return on deserialize exceptions + try { + const transformResult = roleKibanaApplications.map(({ resources, privileges }) => { // if we're dealing with a global entry, which we've ensured above is only possible if it's the only item in the array if (resources.length === 1 && resources[0] === GLOBAL_RESOURCE) { const reservedPrivileges = privileges.filter((privilege) => @@ -246,8 +251,18 @@ function transformRoleApplicationsToKibanaPrivileges( }, {} as RoleKibanaPrivilege['feature']), spaces: resources.map((resource) => ResourceSerializer.deserializeSpaceResource(resource)), }; - }), - }; + }); + + return { + success: true, + value: transformResult, + }; + } catch (e) { + logger.error(`Error transforming Elasticsearch role: ${getDetailedErrorMessage(e)}`); + return { + success: false, + }; + } } const extractUnrecognizedApplicationNames = ( diff --git a/x-pack/plugins/security/server/deprecations/privilege_deprecations.ts b/x-pack/plugins/security/server/deprecations/privilege_deprecations.ts index 7a35a0099e7ac..0742183eb61d4 100644 --- a/x-pack/plugins/security/server/deprecations/privilege_deprecations.ts +++ b/x-pack/plugins/security/server/deprecations/privilege_deprecations.ts @@ -42,7 +42,8 @@ export const getPrivilegeDeprecationsService = ( // @ts-expect-error `SecurityIndicesPrivileges.names` expected to be `string[]` elasticsearchRole, roleName, - authz.applicationName + authz.applicationName, + logger ) ); } catch (e) { diff --git a/x-pack/plugins/security/server/routes/authorization/roles/get.ts b/x-pack/plugins/security/server/routes/authorization/roles/get.ts index 6e010b69a3711..faf166740eab5 100644 --- a/x-pack/plugins/security/server/routes/authorization/roles/get.ts +++ b/x-pack/plugins/security/server/routes/authorization/roles/get.ts @@ -12,7 +12,7 @@ import { wrapIntoCustomErrorResponse } from '../../../errors'; import { createLicensedRouteHandler } from '../../licensed_route_handler'; import { transformElasticsearchRoleToRole } from './model'; -export function defineGetRolesRoutes({ router, authz }: RouteDefinitionParams) { +export function defineGetRolesRoutes({ router, authz, logger }: RouteDefinitionParams) { router.get( { path: '/api/security/role/{name}', @@ -34,7 +34,8 @@ export function defineGetRolesRoutes({ router, authz }: RouteDefinitionParams) { // @ts-expect-error `SecurityIndicesPrivileges.names` expected to be `string[]` elasticsearchRole, request.params.name, - authz.applicationName + authz.applicationName, + logger ), }); } diff --git a/x-pack/plugins/security/server/routes/authorization/roles/get_all.ts b/x-pack/plugins/security/server/routes/authorization/roles/get_all.ts index ba5133b780d5e..9236a6b5577fd 100644 --- a/x-pack/plugins/security/server/routes/authorization/roles/get_all.ts +++ b/x-pack/plugins/security/server/routes/authorization/roles/get_all.ts @@ -11,7 +11,7 @@ import { createLicensedRouteHandler } from '../../licensed_route_handler'; import type { ElasticsearchRole } from './model'; import { transformElasticsearchRoleToRole } from './model'; -export function defineGetAllRolesRoutes({ router, authz }: RouteDefinitionParams) { +export function defineGetAllRolesRoutes({ router, authz, logger }: RouteDefinitionParams) { router.get( { path: '/api/security/role', validate: false }, createLicensedRouteHandler(async (context, request, response) => { @@ -29,7 +29,8 @@ export function defineGetAllRolesRoutes({ router, authz }: RouteDefinitionParams // @ts-expect-error @elastic/elasticsearch SecurityIndicesPrivileges.names expected to be string[] elasticsearchRole, roleName, - authz.applicationName + authz.applicationName, + logger ) ) .sort((roleA, roleB) => {