From 4847e72091de7b17a8c0b4328dc115c9ab4087f9 Mon Sep 17 00:00:00 2001 From: Timothy Sullivan Date: Thu, 14 Oct 2021 18:48:38 -0700 Subject: [PATCH 1/6] [Reporting] Add deprecation messages for roles mapped to reporting_user This fixes the deprecations for various edge cases: - when security was disabled, users saw a meaningless error message - when users did not have manage_security privilege they saw a meaningless error message Adds support for checking deprecations related to xpack.reporting.roles.allow --- .../reporting/server/config/index.test.ts | 2 +- .../plugins/reporting/server/config/index.ts | 2 +- x-pack/plugins/reporting/server/core.ts | 1 + .../__snapshots__/reporting_role.test.ts.snap | 83 +++++++ .../deprecations/reporting_role.test.ts | 165 +++++++------ .../server/deprecations/reporting_role.ts | 232 ++++++++++++++---- .../server/lib/deprecations/index.ts | 74 ++++++ .../server/routes/diagnostic/browser.test.ts | 12 +- .../routes/diagnostic/screenshot.test.ts | 12 +- .../create_mock_reportingplugin.ts | 8 +- 10 files changed, 460 insertions(+), 131 deletions(-) create mode 100644 x-pack/plugins/reporting/server/deprecations/__snapshots__/reporting_role.test.ts.snap diff --git a/x-pack/plugins/reporting/server/config/index.test.ts b/x-pack/plugins/reporting/server/config/index.test.ts index 1a75f6dfec3bd..f77713551592b 100644 --- a/x-pack/plugins/reporting/server/config/index.test.ts +++ b/x-pack/plugins/reporting/server/config/index.test.ts @@ -49,7 +49,7 @@ describe('deprecations', () => { const { messages } = applyReportingDeprecations({ roles: { enabled: true } }); expect(messages).toMatchInlineSnapshot(` Array [ - "Use Kibana application privileges to grant reporting privileges. Using \\"xpack.reporting.roles.allow\\" to grant reporting privileges prevents users from using API Keys to create reports. The \\"xpack.reporting.roles.enabled\\" setting will default to false in a future release.", + "Use Kibana application privileges to grant reporting privileges. Using \\"xpack.reporting.roles.allow\\" to grant reporting privileges is deprecated. The \\"xpack.reporting.roles.enabled\\" setting will default to false in a future release.", ] `); }); diff --git a/x-pack/plugins/reporting/server/config/index.ts b/x-pack/plugins/reporting/server/config/index.ts index 1eeafb4e0c513..ecde65a27623c 100644 --- a/x-pack/plugins/reporting/server/config/index.ts +++ b/x-pack/plugins/reporting/server/config/index.ts @@ -64,7 +64,7 @@ export const config: PluginConfigDescriptor = { defaultMessage: `Use Kibana application privileges to grant reporting privileges.` + ` Using "{fromPath}.roles.allow" to grant reporting privileges` + - ` prevents users from using API Keys to create reports.` + + ` is deprecated.` + ` The "{fromPath}.roles.enabled" setting will default to false` + ` in a future release.`, values: { fromPath }, diff --git a/x-pack/plugins/reporting/server/core.ts b/x-pack/plugins/reporting/server/core.ts index e09cee8c3c7c2..a4986acc0253b 100644 --- a/x-pack/plugins/reporting/server/core.ts +++ b/x-pack/plugins/reporting/server/core.ts @@ -72,6 +72,7 @@ export class ReportingCore { public getContract: () => ReportingSetup; constructor(private logger: LevelLogger, context: PluginInitializerContext) { + // TODO: capture the entire packageInfo so we can form documentation links on the server this.kibanaVersion = context.env.packageInfo.version; const syncConfig = context.config.get(); this.deprecatedAllowedRoles = syncConfig.roles.enabled ? syncConfig.roles.allow : false; diff --git a/x-pack/plugins/reporting/server/deprecations/__snapshots__/reporting_role.test.ts.snap b/x-pack/plugins/reporting/server/deprecations/__snapshots__/reporting_role.test.ts.snap new file mode 100644 index 0000000000000..df430b301eb44 --- /dev/null +++ b/x-pack/plugins/reporting/server/deprecations/__snapshots__/reporting_role.test.ts.snap @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`roles mapped to a deprecated role logs a deprecation when a role was found that maps to a deprecated custom role from the roles.allow setting 1`] = ` +Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ + "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml", + "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml", + "Create one or more custom roles that provide Kibana application privileges to reporting features in **Management > Security > Roles**.", + "Assign the custom role(s) as desired. You may remove the \\"reporting_user\\" role from the user(s) .", + "Remove the role that grants Reporting privilege from all role mappings and add the custom role. The affected role mappings are: dungeon_master[my_test_reporting_user].", + ], + }, + "deprecationType": "feature", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/secure-reporting.html#grant-user-access", + "level": "warning", + "message": "Existing roles are mapped to a deprecated role for Reporting privileges", + "title": "The \\"reporting_user\\" role is deprecated: check role mappings", + }, +] +`; + +exports[`roles mapped to a deprecated role logs a deprecation when a role was found that maps to the deprecated reporting_user role 1`] = ` +Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ + "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml", + "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml", + "Create one or more custom roles that provide Kibana application privileges to reporting features in **Management > Security > Roles**.", + "Assign the custom role(s) as desired. You may remove the \\"reporting_user\\" role from the user(s) .", + "Remove the role that grants Reporting privilege from all role mappings and add the custom role. The affected role mappings are: dungeon_master[reporting_user].", + ], + }, + "deprecationType": "feature", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/secure-reporting.html#grant-user-access", + "level": "warning", + "message": "Existing roles are mapped to a deprecated role for Reporting privileges", + "title": "The \\"reporting_user\\" role is deprecated: check role mappings", + }, +] +`; + +exports[`users assigned to a deprecated role logs a deprecation when a user was found with a deprecated custom role from the roles.allow setting 1`] = ` +Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ + "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml", + "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml", + "Create one or more custom roles that provide Kibana application privileges to reporting features in **Management > Security > Roles**.", + "Assign the custom role(s) as desired. You may remove the \\"reporting_user\\" role from the user(s). The affected users are: reportron[my_test_reporting_user].", + ], + }, + "deprecationType": "feature", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/secure-reporting.html#grant-user-access", + "level": "warning", + "message": "Existing users have their Reporting privilege granted by a deprecated setting.", + "title": "The \\"reporting_user\\" role is deprecated: check user roles", + }, +] +`; + +exports[`users assigned to a deprecated role logs a deprecation when a user was found with a deprecated reporting_user role 1`] = ` +Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ + "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml", + "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml", + "Create one or more custom roles that provide Kibana application privileges to reporting features in **Management > Security > Roles**.", + "Assign the custom role(s) as desired. You may remove the \\"reporting_user\\" role from the user(s). The affected users are: reportron[reporting_user].", + ], + }, + "deprecationType": "feature", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/secure-reporting.html#grant-user-access", + "level": "warning", + "message": "Existing users have their Reporting privilege granted by a deprecated setting.", + "title": "The \\"reporting_user\\" role is deprecated: check user roles", + }, +] +`; diff --git a/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts b/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts index 5b0719bf6e6b6..da08ea8e091c4 100644 --- a/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts +++ b/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts @@ -5,11 +5,15 @@ * 2.0. */ +import { GetDeprecationsContext, IScopedClusterClient } from 'kibana/server'; +import { elasticsearchServiceMock } from 'src/core/server/mocks'; import { ReportingCore } from '..'; +import { + createMockConfigSchema, + createMockPluginSetup, + createMockReportingCore, +} from '../test_helpers'; import { getDeprecationsInfo } from './reporting_role'; -import { createMockConfigSchema, createMockReportingCore } from '../test_helpers'; -import { elasticsearchServiceMock } from 'src/core/server/mocks'; -import { GetDeprecationsContext, IScopedClusterClient } from 'kibana/server'; let reportingCore: ReportingCore; let context: GetDeprecationsContext; @@ -18,6 +22,7 @@ let esClient: jest.Mocked; beforeEach(async () => { const mockReportingConfig = createMockConfigSchema({ roles: { enabled: false } }); reportingCore = await createMockReportingCore(mockReportingConfig); + esClient = elasticsearchServiceMock.createScopedClusterClient(); esClient.asCurrentUser.security.getUser = jest.fn().mockResolvedValue({ body: { xyz: { username: 'normal_user', roles: ['data_analyst'] } }, @@ -26,95 +31,111 @@ beforeEach(async () => { }); test('logs no deprecations when setup has no issues', async () => { - expect( - await getDeprecationsInfo(context, { - reportingCore, - }) - ).toMatchInlineSnapshot(`Array []`); + expect(await getDeprecationsInfo(context, { reportingCore })).toMatchInlineSnapshot(`Array []`); }); -test('logs a plain message when only a reporting_user role issue is found', async () => { - esClient.asCurrentUser.security.getUser = jest.fn().mockResolvedValue({ - body: { reportron: { username: 'reportron', roles: ['kibana_admin', 'reporting_user'] } }, +describe('users assigned to a deprecated role', () => { + test('logs a deprecation when a user was found with a deprecated reporting_user role', async () => { + esClient.asCurrentUser.security.getUser = jest.fn().mockResolvedValue({ + body: { reportron: { username: 'reportron', roles: ['kibana_admin', 'reporting_user'] } }, + }); + + const mockReportingConfig = createMockConfigSchema({ roles: { enabled: true } }); + reportingCore = await createMockReportingCore(mockReportingConfig); + + expect(await getDeprecationsInfo(context, { reportingCore })).toMatchSnapshot(); }); - expect( - await getDeprecationsInfo(context, { - reportingCore, - }) - ).toMatchInlineSnapshot(` - Array [ - Object { - "correctiveActions": Object { - "manualSteps": Array [ - "Create one or more custom roles that provide Kibana application privileges to reporting features in **Management > Security > Roles**.", - "Assign the custom role(s) as desired, and remove the \\"reporting_user\\" role from the user(s).", - ], - }, - "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/secure-reporting.html", - "level": "critical", - "message": "The deprecated \\"reporting_user\\" role has been found for 1 user(s): \\"reportron\\"", - "title": "Found deprecated reporting role", + + test('logs a deprecation when a user was found with a deprecated custom role from the roles.allow setting', async () => { + reportingCore = await createMockReportingCore( + createMockConfigSchema({ roles: { enabled: true, allow: ['my_test_reporting_user'] } }) + ); + esClient.asCurrentUser.security.getUser = jest.fn().mockResolvedValue({ + body: { + reportron: { username: 'reportron', roles: ['kibana_admin', 'my_test_reporting_user'] }, }, - ] - `); + }); + + expect(await getDeprecationsInfo(context, { reportingCore })).toMatchSnapshot(); + }); }); -test('logs multiple entries when multiple reporting_user role issues are found', async () => { - esClient.asCurrentUser.security.getUser = jest.fn().mockResolvedValue({ - body: { - reportron: { username: 'reportron', roles: ['kibana_admin', 'reporting_user'] }, - supercooluser: { username: 'supercooluser', roles: ['kibana_admin', 'reporting_user'] }, - }, +describe('roles mapped to a deprecated role', () => { + test('logs a deprecation when a role was found that maps to the deprecated reporting_user role', async () => { + esClient.asCurrentUser.security.getRoleMapping = jest.fn().mockResolvedValue({ + body: { dungeon_master: { roles: ['reporting_user'] } }, + }); + + const mockReportingConfig = createMockConfigSchema({ roles: { enabled: true } }); + reportingCore = await createMockReportingCore(mockReportingConfig); + + expect(await getDeprecationsInfo(context, { reportingCore })).toMatchSnapshot(); }); - expect( - await getDeprecationsInfo(context, { - reportingCore, - }) - ).toMatchInlineSnapshot(` + test('logs a deprecation when a role was found that maps to a deprecated custom role from the roles.allow setting', async () => { + reportingCore = await createMockReportingCore( + createMockConfigSchema({ roles: { enabled: true, allow: ['my_test_reporting_user'] } }) + ); + esClient.asCurrentUser.security.getRoleMapping = jest.fn().mockResolvedValue({ + body: { dungeon_master: { roles: ['my_test_reporting_user'] } }, + }); + + expect(await getDeprecationsInfo(context, { reportingCore })).toMatchSnapshot(); + }); +}); + +describe('check deprecations when security is disabled', () => { + test('logs no deprecations: roles enabled', async () => { + const mockReportingConfig = createMockConfigSchema({ roles: { enabled: false } }); + reportingCore = await createMockReportingCore( + mockReportingConfig, + createMockPluginSetup({ security: null }) + ); + expect(await getDeprecationsInfo(context, { reportingCore })).toMatchInlineSnapshot(`Array []`); + }); + + test('logs no deprecations: roles not enabled', async () => { + const mockReportingConfig = createMockConfigSchema(); // roles.enabled: true is default in 7.x / 8.0 + reportingCore = await createMockReportingCore( + mockReportingConfig, + createMockPluginSetup({ security: null }) + ); + + expect(await getDeprecationsInfo(context, { reportingCore })).toMatchInlineSnapshot(`Array []`); + }); +}); + +it('insufficient permissions', async () => { + const permissionsError = new Error('you shall not pass'); + (permissionsError as unknown as { statusCode: number }).statusCode = 403; + esClient.asCurrentUser.security.getUser = jest.fn().mockRejectedValue(permissionsError); + esClient.asCurrentUser.security.getRoleMapping = jest.fn().mockRejectedValue(permissionsError); + + expect(await getDeprecationsInfo(context, { reportingCore })).toMatchInlineSnapshot(` Array [ Object { "correctiveActions": Object { "manualSteps": Array [ - "Create one or more custom roles that provide Kibana application privileges to reporting features in **Management > Security > Roles**.", - "Assign the custom role(s) as desired, and remove the \\"reporting_user\\" role from the user(s).", + "Make sure you have a \\"manage_security\\" cluster privilege assigned.", ], }, - "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/secure-reporting.html", - "level": "critical", - "message": "The deprecated \\"reporting_user\\" role has been found for 2 user(s): \\"reportron\\", \\"supercooluser\\"", - "title": "Found deprecated reporting role", + "deprecationType": "feature", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/xpack-security.html#_required_permissions_7", + "level": "fetch_error", + "message": "You do not have enough permissions to fix this deprecation.", + "title": "The \\"reporting_user\\" role is deprecated: check user roles", }, - ] - `); -}); - -test('logs an expanded message when a config issue and a reporting_user role issue is found', async () => { - esClient.asCurrentUser.security.getUser = jest.fn().mockResolvedValue({ - body: { reportron: { username: 'reportron', roles: ['kibana_admin', 'reporting_user'] } }, - }); - - const mockReportingConfig = createMockConfigSchema({ roles: { enabled: true } }); - reportingCore = await createMockReportingCore(mockReportingConfig); - - expect( - await getDeprecationsInfo(context, { - reportingCore, - }) - ).toMatchInlineSnapshot(` - Array [ Object { "correctiveActions": Object { "manualSteps": Array [ - "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml", - "Create one or more custom roles that provide Kibana application privileges to reporting features in **Management > Security > Roles**.", - "Assign the custom role(s) as desired, and remove the \\"reporting_user\\" role from the user(s).", + "Make sure you have a \\"manage_security\\" cluster privilege assigned.", ], }, - "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/secure-reporting.html", - "level": "critical", - "message": "The deprecated \\"reporting_user\\" role has been found for 1 user(s): \\"reportron\\"", - "title": "Found deprecated reporting role", + "deprecationType": "feature", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/xpack-security.html#_required_permissions_7", + "level": "fetch_error", + "message": "You do not have enough permissions to fix this deprecation.", + "title": "The \\"reporting_user\\" role is deprecated: check role mappings", }, ] `); diff --git a/x-pack/plugins/reporting/server/deprecations/reporting_role.ts b/x-pack/plugins/reporting/server/deprecations/reporting_role.ts index 6e08169727d1b..fad35cb933fa9 100644 --- a/x-pack/plugins/reporting/server/deprecations/reporting_role.ts +++ b/x-pack/plugins/reporting/server/deprecations/reporting_role.ts @@ -5,65 +5,209 @@ * 2.0. */ -import type { GetDeprecationsContext, DeprecationsDetails } from 'src/core/server'; +import { + SecurityGetRoleMappingResponse, + SecurityGetUserResponse, +} from '@elastic/elasticsearch/api/types'; import { i18n } from '@kbn/i18n'; -import { ReportingCore } from '..'; +import type { + DeprecationsDetails, + ElasticsearchClient, + GetDeprecationsContext, +} from 'src/core/server'; +import { ReportingCore } from '../'; +import { deprecations } from '../lib/deprecations'; + +const REPORTING_USER_ROLE_NAME = 'reporting_user'; +const DOCUMENTATION_URL = + 'https://www.elastic.co/guide/en/kibana/current/secure-reporting.html#grant-user-access'; -const deprecatedRole = 'reporting_user'; const upgradableConfig = 'xpack.reporting.roles.enabled: false'; +const incompatibleConfig = 'xpack.reporting.roles.allow'; interface ExtraDependencies { reportingCore: ReportingCore; } -export const getDeprecationsInfo = async ( +export async function getDeprecationsInfo( { esClient }: GetDeprecationsContext, { reportingCore }: ExtraDependencies -): Promise => { - const usingDeprecatedConfig = !reportingCore.getContract().usesUiCapabilities(); - const deprecations: DeprecationsDetails[] = []; - const { body: users } = await esClient.asCurrentUser.security.getUser(); +): Promise { + const client = esClient.asCurrentUser; + const { security } = reportingCore.getPluginSetupDeps(); + + // Nothing to do if security is disabled + if (!security) { + return []; + } - const reportingUsers = Object.entries(users) - .filter(([, user]) => user.roles.includes(deprecatedRole)) - .map(([, user]) => user.username); + const config = reportingCore.getConfig(); + const deprecatedRoles = config.get('roles', 'allow') || ['reporting_user']; - const numReportingUsers = reportingUsers.length; + return [ + ...(await getUsersDeprecations(client, reportingCore, deprecatedRoles)), + ...(await getRoleMappingsDeprecations(client, reportingCore, deprecatedRoles)), + ]; +} - if (numReportingUsers > 0) { - deprecations.push({ - title: i18n.translate('xpack.reporting.deprecations.reportingRoleTitle', { - defaultMessage: 'Found deprecated reporting role', +async function getUsersDeprecations( + client: ElasticsearchClient, + reportingCore: ReportingCore, + deprecatedRoles: string[] +): Promise { + const strings = { + title: i18n.translate('xpack.reporting.deprecations.reportingRoleUsersTitle', { + defaultMessage: `The "{reportingUserRoleName}" role is deprecated: check user roles`, + values: { reportingUserRoleName: REPORTING_USER_ROLE_NAME }, + }), + message: i18n.translate('xpack.reporting.deprecations.reportingRoleUsersMessage', { + defaultMessage: `Existing users have their Reporting privilege granted by a deprecated setting.`, + }), + manualSteps: (usersRoles: string) => [ + i18n.translate('xpack.reporting.deprecations.reportingRoleUsers.manualStepOne', { + defaultMessage: 'Set "{upgradableConfig}" in kibana.yml', + values: { upgradableConfig }, }), - message: i18n.translate('xpack.reporting.deprecations.reportingRoleMessage', { + i18n.translate('xpack.reporting.deprecations.reportingRoleUsers.manualStepTwo', { + defaultMessage: 'Remove "{incompatibleConfig}" in kibana.yml', + values: { incompatibleConfig }, + }), + i18n.translate('xpack.reporting.deprecations.reportingRoleUsers.manualStepThree', { defaultMessage: - 'The deprecated "{deprecatedRole}" role has been found for {numReportingUsers} user(s): "{usernames}"', - values: { deprecatedRole, numReportingUsers, usernames: reportingUsers.join('", "') }, + `Create one or more custom roles that provide Kibana application` + + ` privileges to reporting features in **Management > Security > Roles**.`, }), - documentationUrl: 'https://www.elastic.co/guide/en/kibana/current/secure-reporting.html', - level: 'critical', - correctiveActions: { - manualSteps: [ - ...(usingDeprecatedConfig - ? [ - i18n.translate('xpack.reporting.deprecations.reportingRole.manualStepOneMessage', { - defaultMessage: 'Set "{upgradableConfig}" in kibana.yml', - values: { upgradableConfig }, - }), - ] - : []), - i18n.translate('xpack.reporting.deprecations.reportingRole.manualStepTwoMessage', { - defaultMessage: `Create one or more custom roles that provide Kibana application privileges to reporting features in **Management > Security > Roles**.`, - }), - i18n.translate('xpack.reporting.deprecations.reportingRole.manualStepThreeMessage', { - defaultMessage: - 'Assign the custom role(s) as desired, and remove the "{deprecatedRole}" role from the user(s).', - values: { deprecatedRole }, - }), - ], - }, - }); + i18n.translate('xpack.reporting.deprecations.reportingRoleUsers.manualStepFour', { + defaultMessage: + 'Assign the custom role(s) as desired. You may remove the "{deprecatedRole}" role from the user(s). The affected users are: {usersRoles}.', + values: { deprecatedRole: `reporting_user`, usersRoles }, + }), + ], + }; + + let users: SecurityGetUserResponse; + try { + users = (await client.security.getUser()).body; + } catch (err) { + const { logger } = reportingCore.getPluginSetupDeps(); + if (deprecations.getErrorStatusCode(err) === 403) { + logger.warn( + `Failed to retrieve users when checking for deprecations:` + + ` the "manage_security" cluster privilege is required.` + ); + } else { + logger.error( + `Failed to retrieve users when checking for deprecations,` + + ` unexpected error: ${deprecations.getDetailedErrorMessage(err)}.` + ); + } + return deprecations.deprecationError(strings.title, err); + } + + const reportingUsers = Object.entries(users).reduce((userSet, current) => { + const [userName, user] = current; + const foundRole = user.roles.find((role) => deprecatedRoles.includes(role)); + return foundRole ? [...userSet, `${userName}[${foundRole}]`] : userSet; + }, [] as string[]); + + if (reportingUsers.length === 0) { + return []; + } + + return [ + { + title: strings.title, + message: strings.message, + correctiveActions: { manualSteps: strings.manualSteps(reportingUsers.join(', ')) }, + level: 'warning', + deprecationType: 'feature', + documentationUrl: DOCUMENTATION_URL, + }, + ]; +} + +async function getRoleMappingsDeprecations( + client: ElasticsearchClient, + reportingCore: ReportingCore, + deprecatedRoles: string[] +): Promise { + const strings = { + title: i18n.translate('xpack.reporting.deprecations.reportingRoleMappingsTitle', { + defaultMessage: `The "{reportingUserRoleName}" role is deprecated: check role mappings`, + values: { reportingUserRoleName: REPORTING_USER_ROLE_NAME }, + }), + message: i18n.translate('xpack.reporting.deprecations.reportingRoleMappingsMessage', { + defaultMessage: `Existing roles are mapped to a deprecated role for Reporting privileges`, + }), + manualSteps: (roleMappings: string) => [ + i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepOne', { + defaultMessage: 'Set "{upgradableConfig}" in kibana.yml', + values: { upgradableConfig }, + }), + i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepTwo', { + defaultMessage: 'Remove "{incompatibleConfig}" in kibana.yml', + values: { incompatibleConfig }, + }), + i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepThree', { + defaultMessage: + `Create one or more custom roles that provide Kibana application` + + ` privileges to reporting features in **Management > Security > Roles**.`, + }), + i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepFour', { + defaultMessage: + 'Assign the custom role(s) as desired. You may remove the "{deprecatedRole}" role from the user(s) .', + values: { deprecatedRole: `reporting_user` }, + }), + i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepFive', { + defaultMessage: + 'Remove the role that grants Reporting privilege from all role mappings and add the custom role. The affected role mappings are: {roleMappings}.', + values: { roleMappings }, + }), + ], + }; + + let roleMappings: SecurityGetRoleMappingResponse; + try { + roleMappings = (await client.security.getRoleMapping()).body; + } catch (err) { + const { logger } = reportingCore.getPluginSetupDeps(); + if (deprecations.getErrorStatusCode(err) === 403) { + logger.warn( + `Failed to retrieve role mappings when checking for deprecations:` + + ` the "manage_security" cluster privilege is required.` + ); + } else { + logger.error( + `Failed to retrieve role mappings when checking for deprecations,` + + ` unexpected error: ${deprecations.getDetailedErrorMessage(err)}.` + ); + } + return deprecations.deprecationError(strings.title, err); + } + + const roleMappingsWithReportingRole: string[] = Object.entries(roleMappings).reduce( + (roleSet, current) => { + const [roleName, role] = current; + const foundMapping = role.roles.find((roll) => deprecatedRoles.includes(roll)); + return foundMapping ? [...roleSet, `${roleName}[${foundMapping}]`] : roleSet; + }, + [] as string[] + ); + + if (roleMappingsWithReportingRole.length === 0) { + return []; } - return deprecations; -}; + return [ + { + title: strings.title, + message: strings.message, + correctiveActions: { + manualSteps: strings.manualSteps(roleMappingsWithReportingRole.join(', ')), + }, + level: 'warning', + deprecationType: 'feature', + documentationUrl: DOCUMENTATION_URL, + }, + ]; +} diff --git a/x-pack/plugins/reporting/server/lib/deprecations/index.ts b/x-pack/plugins/reporting/server/lib/deprecations/index.ts index 95594940e07e2..2d55c3b4c22d8 100644 --- a/x-pack/plugins/reporting/server/lib/deprecations/index.ts +++ b/x-pack/plugins/reporting/server/lib/deprecations/index.ts @@ -5,8 +5,82 @@ * 2.0. */ +import { errors } from '@elastic/elasticsearch'; +import Boom from '@hapi/boom'; +import { i18n } from '@kbn/i18n'; +import { DeprecationsDetails } from 'kibana/server'; import { checkIlmMigrationStatus } from './check_ilm_migration_status'; +function deprecationError(title: string, error: Error): DeprecationsDetails[] { + if (getErrorStatusCode(error) === 403) { + return [ + { + title, + level: 'fetch_error', // NOTE: is fetch_error not shown in the Upgrade Assistant UI? + deprecationType: 'feature', + message: i18n.translate( + 'xpack.reporting.deprecations.reportingRole.forbiddenErrorMessage', + { defaultMessage: 'You do not have enough permissions to fix this deprecation.' } + ), + documentationUrl: `https://www.elastic.co/guide/en/kibana/current/xpack-security.html#_required_permissions_7`, + correctiveActions: { + manualSteps: [ + i18n.translate( + 'xpack.reporting.deprecations.reportingRole.forbiddenErrorCorrectiveAction', + { + defaultMessage: + 'Make sure you have a "manage_security" cluster privilege assigned.', + } + ), + ], + }, + }, + ]; + } + + return [ + { + title, + level: 'fetch_error', // NOTE: is fetch_error not shown in the Upgrade Assistant UI? + deprecationType: 'feature', + message: i18n.translate('xpack.reporting.deprecations.reportingRole.unknownErrorMessage', { + defaultMessage: 'Failed to perform deprecation check. Check Kibana logs for more details.', + }), + correctiveActions: { + manualSteps: [ + i18n.translate( + 'xpack.reporting.deprecations.reportingRole.unknownErrorCorrectiveAction', + { defaultMessage: 'Check Kibana logs for more details.' } + ), + ], + }, + }, + ]; +} + +function getErrorStatusCode(error: any): number { + if (error instanceof errors.ResponseError) { + return error.statusCode; + } + + return Boom.isBoom(error) ? error.output.statusCode : error.statusCode || error.status; +} + +function getDetailedErrorMessage(error: any): string { + if (error instanceof errors.ResponseError) { + return JSON.stringify(error.body); + } + + if (Boom.isBoom(error)) { + return JSON.stringify(error.output.payload); + } + + return error.message; +} + export const deprecations = { checkIlmMigrationStatus, + deprecationError, + getDetailedErrorMessage, + getErrorStatusCode, }; diff --git a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts index f32e1b437bc33..7677f37702f0d 100644 --- a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts +++ b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts @@ -52,11 +52,13 @@ describe('POST /diagnose/browser', () => { () => ({ usesUiCapabilities: () => false }) ); - const mockSetupDeps = createMockPluginSetup({ - router: httpSetup.createRouter(''), - }); - - core = await createMockReportingCore(config, mockSetupDeps); + core = await createMockReportingCore( + config, + createMockPluginSetup({ + router: httpSetup.createRouter(''), + security: null, + }) + ); mockedSpawn.mockImplementation(() => ({ removeAllListeners: jest.fn(), diff --git a/x-pack/plugins/reporting/server/routes/diagnostic/screenshot.test.ts b/x-pack/plugins/reporting/server/routes/diagnostic/screenshot.test.ts index 6d844f9637a0b..dd543707fe66a 100644 --- a/x-pack/plugins/reporting/server/routes/diagnostic/screenshot.test.ts +++ b/x-pack/plugins/reporting/server/routes/diagnostic/screenshot.test.ts @@ -50,11 +50,13 @@ describe('POST /diagnose/screenshot', () => { () => ({ usesUiCapabilities: () => false }) ); - const mockSetupDeps = createMockPluginSetup({ - router: httpSetup.createRouter(''), - }); - - core = await createMockReportingCore(config, mockSetupDeps); + core = await createMockReportingCore( + config, + createMockPluginSetup({ + router: httpSetup.createRouter(''), + security: null, + }) + ); }); afterEach(async () => { diff --git a/x-pack/plugins/reporting/server/test_helpers/create_mock_reportingplugin.ts b/x-pack/plugins/reporting/server/test_helpers/create_mock_reportingplugin.ts index 9e58d6d4efa41..d62cc750ccfcc 100644 --- a/x-pack/plugins/reporting/server/test_helpers/create_mock_reportingplugin.ts +++ b/x-pack/plugins/reporting/server/test_helpers/create_mock_reportingplugin.ts @@ -12,11 +12,13 @@ jest.mock('../browsers'); import _ from 'lodash'; import * as Rx from 'rxjs'; import { coreMock, elasticsearchServiceMock } from 'src/core/server/mocks'; -import { FieldFormatsRegistry } from 'src/plugins/field_formats/common'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { dataPluginMock } from 'src/plugins/data/server/mocks'; +import { FieldFormatsRegistry } from 'src/plugins/field_formats/common'; import { ReportingConfig, ReportingCore } from '../'; import { featuresPluginMock } from '../../../features/server/mocks'; +import { securityMock } from '../../../security/server/mocks'; +import { taskManagerMock } from '../../../task_manager/server/mocks'; import { chromium, HeadlessChromiumDriverFactory, @@ -39,9 +41,9 @@ export const createMockPluginSetup = (setupMock?: any): ReportingInternalSetup = features: featuresPluginMock.createSetup(), basePath: { set: jest.fn() }, router: setupMock.router, - security: setupMock.security, + security: securityMock.createSetup(), licensing: { license$: Rx.of({ isAvailable: true, isActive: true, type: 'basic' }) } as any, - taskManager: { registerTaskDefinitions: jest.fn() } as any, + taskManager: taskManagerMock.createSetup(), logger: createMockLevelLogger(), ...setupMock, }; From e1697d295f1529bc82618839b7f5dc2e48e59396 Mon Sep 17 00:00:00 2001 From: Timothy Sullivan Date: Wed, 20 Oct 2021 11:54:34 -0700 Subject: [PATCH 2/6] updates to content per feedback --- .../plugins/reporting/server/config/index.ts | 3 + .../__snapshots__/reporting_role.test.ts.snap | 44 +++++------ .../server/deprecations/reporting_role.ts | 73 ++++++++++--------- 3 files changed, 62 insertions(+), 58 deletions(-) diff --git a/x-pack/plugins/reporting/server/config/index.ts b/x-pack/plugins/reporting/server/config/index.ts index ecde65a27623c..244a4577813da 100644 --- a/x-pack/plugins/reporting/server/config/index.ts +++ b/x-pack/plugins/reporting/server/config/index.ts @@ -74,6 +74,9 @@ export const config: PluginConfigDescriptor = { i18n.translate('xpack.reporting.deprecations.reportingRoles.manualStepOne', { defaultMessage: `Set "xpack.reporting.roles.enabled" to "false" in kibana.yml.`, }), + i18n.translate('xpack.reporting.deprecations.reportingRoles.manualStepOnePartOne', { + defaultMessage: `Remove "xpack.reporting.roles.allow" to "false" in kibana.yml, if present.`, + }), i18n.translate('xpack.reporting.deprecations.reportingRoles.manualStepTwo', { defaultMessage: `Create one or more roles that grant the Kibana application` + diff --git a/x-pack/plugins/reporting/server/deprecations/__snapshots__/reporting_role.test.ts.snap b/x-pack/plugins/reporting/server/deprecations/__snapshots__/reporting_role.test.ts.snap index df430b301eb44..5afed2c4c4e1f 100644 --- a/x-pack/plugins/reporting/server/deprecations/__snapshots__/reporting_role.test.ts.snap +++ b/x-pack/plugins/reporting/server/deprecations/__snapshots__/reporting_role.test.ts.snap @@ -5,15 +5,15 @@ Array [ Object { "correctiveActions": Object { "manualSteps": Array [ - "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml", - "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml", - "Create one or more custom roles that provide Kibana application privileges to reporting features in **Management > Security > Roles**.", - "Assign the custom role(s) as desired. You may remove the \\"reporting_user\\" role from the user(s) .", - "Remove the role that grants Reporting privilege from all role mappings and add the custom role. The affected role mappings are: dungeon_master[my_test_reporting_user].", + "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml.", + "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml, if present.", + "Create one or more custom roles that provide Kibana application privileges to reporting features in Management > Security > Roles.", + "Create a custom role with Kibana privileges to grant access to Reporting.", + "Remove the \\"reporting_user\\" role from all role mappings and add the custom role. The affected role mappings are: dungeon_master[my_test_reporting_user].", ], }, "deprecationType": "feature", - "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/secure-reporting.html#grant-user-access", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/kibana-privileges.html", "level": "warning", "message": "Existing roles are mapped to a deprecated role for Reporting privileges", "title": "The \\"reporting_user\\" role is deprecated: check role mappings", @@ -26,15 +26,15 @@ Array [ Object { "correctiveActions": Object { "manualSteps": Array [ - "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml", - "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml", - "Create one or more custom roles that provide Kibana application privileges to reporting features in **Management > Security > Roles**.", - "Assign the custom role(s) as desired. You may remove the \\"reporting_user\\" role from the user(s) .", - "Remove the role that grants Reporting privilege from all role mappings and add the custom role. The affected role mappings are: dungeon_master[reporting_user].", + "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml.", + "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml, if present.", + "Create one or more custom roles that provide Kibana application privileges to reporting features in Management > Security > Roles.", + "Create a custom role with Kibana privileges to grant access to Reporting.", + "Remove the \\"reporting_user\\" role from all role mappings and add the custom role. The affected role mappings are: dungeon_master[reporting_user].", ], }, "deprecationType": "feature", - "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/secure-reporting.html#grant-user-access", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/kibana-privileges.html", "level": "warning", "message": "Existing roles are mapped to a deprecated role for Reporting privileges", "title": "The \\"reporting_user\\" role is deprecated: check role mappings", @@ -47,14 +47,14 @@ Array [ Object { "correctiveActions": Object { "manualSteps": Array [ - "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml", - "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml", - "Create one or more custom roles that provide Kibana application privileges to reporting features in **Management > Security > Roles**.", - "Assign the custom role(s) as desired. You may remove the \\"reporting_user\\" role from the user(s). The affected users are: reportron[my_test_reporting_user].", + "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml.", + "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml, if present.", + "Create a custom role with Kibana privileges to grant access to Reporting.", + "Remove the \\"reporting_user\\" role from all users and add the custom role. The affected users are: reportron[my_test_reporting_user].", ], }, "deprecationType": "feature", - "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/secure-reporting.html#grant-user-access", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/kibana-privileges.html", "level": "warning", "message": "Existing users have their Reporting privilege granted by a deprecated setting.", "title": "The \\"reporting_user\\" role is deprecated: check user roles", @@ -67,14 +67,14 @@ Array [ Object { "correctiveActions": Object { "manualSteps": Array [ - "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml", - "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml", - "Create one or more custom roles that provide Kibana application privileges to reporting features in **Management > Security > Roles**.", - "Assign the custom role(s) as desired. You may remove the \\"reporting_user\\" role from the user(s). The affected users are: reportron[reporting_user].", + "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml.", + "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml, if present.", + "Create a custom role with Kibana privileges to grant access to Reporting.", + "Remove the \\"reporting_user\\" role from all users and add the custom role. The affected users are: reportron[reporting_user].", ], }, "deprecationType": "feature", - "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/secure-reporting.html#grant-user-access", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/kibana-privileges.html", "level": "warning", "message": "Existing users have their Reporting privilege granted by a deprecated setting.", "title": "The \\"reporting_user\\" role is deprecated: check user roles", diff --git a/x-pack/plugins/reporting/server/deprecations/reporting_role.ts b/x-pack/plugins/reporting/server/deprecations/reporting_role.ts index fad35cb933fa9..18df3c583555b 100644 --- a/x-pack/plugins/reporting/server/deprecations/reporting_role.ts +++ b/x-pack/plugins/reporting/server/deprecations/reporting_role.ts @@ -19,11 +19,7 @@ import { ReportingCore } from '../'; import { deprecations } from '../lib/deprecations'; const REPORTING_USER_ROLE_NAME = 'reporting_user'; -const DOCUMENTATION_URL = - 'https://www.elastic.co/guide/en/kibana/current/secure-reporting.html#grant-user-access'; - -const upgradableConfig = 'xpack.reporting.roles.enabled: false'; -const incompatibleConfig = 'xpack.reporting.roles.allow'; +const DOCUMENTATION_URL = 'https://www.elastic.co/guide/en/kibana/current/kibana-privileges.html'; interface ExtraDependencies { reportingCore: ReportingCore; @@ -55,32 +51,35 @@ async function getUsersDeprecations( reportingCore: ReportingCore, deprecatedRoles: string[] ): Promise { + const usingDeprecatedConfig = !reportingCore.getContract().usesUiCapabilities(); const strings = { title: i18n.translate('xpack.reporting.deprecations.reportingRoleUsersTitle', { - defaultMessage: `The "{reportingUserRoleName}" role is deprecated: check user roles`, + defaultMessage: 'The "{reportingUserRoleName}" role is deprecated: check user roles', values: { reportingUserRoleName: REPORTING_USER_ROLE_NAME }, }), message: i18n.translate('xpack.reporting.deprecations.reportingRoleUsersMessage', { - defaultMessage: `Existing users have their Reporting privilege granted by a deprecated setting.`, + defaultMessage: + 'Existing users have their Reporting privilege granted by a deprecated setting.', }), manualSteps: (usersRoles: string) => [ - i18n.translate('xpack.reporting.deprecations.reportingRoleUsers.manualStepOne', { - defaultMessage: 'Set "{upgradableConfig}" in kibana.yml', - values: { upgradableConfig }, - }), - i18n.translate('xpack.reporting.deprecations.reportingRoleUsers.manualStepTwo', { - defaultMessage: 'Remove "{incompatibleConfig}" in kibana.yml', - values: { incompatibleConfig }, - }), + ...(usingDeprecatedConfig + ? [ + i18n.translate('xpack.reporting.deprecations.reportingRoleUsers.manualStepOne', { + defaultMessage: 'Set "xpack.reporting.roles.enabled: false" in kibana.yml.', + }), + i18n.translate('xpack.reporting.deprecations.reportingRoleUsers.manualStepTwo', { + defaultMessage: 'Remove "xpack.reporting.roles.allow" in kibana.yml, if present.', + }), + ] + : []), + i18n.translate('xpack.reporting.deprecations.reportingRoleUsers.manualStepThree', { - defaultMessage: - `Create one or more custom roles that provide Kibana application` + - ` privileges to reporting features in **Management > Security > Roles**.`, + defaultMessage: 'Create a custom role with Kibana privileges to grant access to Reporting.', }), i18n.translate('xpack.reporting.deprecations.reportingRoleUsers.manualStepFour', { defaultMessage: - 'Assign the custom role(s) as desired. You may remove the "{deprecatedRole}" role from the user(s). The affected users are: {usersRoles}.', - values: { deprecatedRole: `reporting_user`, usersRoles }, + 'Remove the "reporting_user" role from all users and add the custom role. The affected users are: {usersRoles}.', + values: { usersRoles }, }), ], }; @@ -131,36 +130,38 @@ async function getRoleMappingsDeprecations( reportingCore: ReportingCore, deprecatedRoles: string[] ): Promise { + const usingDeprecatedConfig = !reportingCore.getContract().usesUiCapabilities(); const strings = { title: i18n.translate('xpack.reporting.deprecations.reportingRoleMappingsTitle', { - defaultMessage: `The "{reportingUserRoleName}" role is deprecated: check role mappings`, + defaultMessage: 'The "{reportingUserRoleName}" role is deprecated: check role mappings', values: { reportingUserRoleName: REPORTING_USER_ROLE_NAME }, }), message: i18n.translate('xpack.reporting.deprecations.reportingRoleMappingsMessage', { - defaultMessage: `Existing roles are mapped to a deprecated role for Reporting privileges`, + defaultMessage: 'Existing roles are mapped to a deprecated role for Reporting privileges', }), manualSteps: (roleMappings: string) => [ - i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepOne', { - defaultMessage: 'Set "{upgradableConfig}" in kibana.yml', - values: { upgradableConfig }, - }), - i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepTwo', { - defaultMessage: 'Remove "{incompatibleConfig}" in kibana.yml', - values: { incompatibleConfig }, - }), + ...(usingDeprecatedConfig + ? [ + i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepOne', { + defaultMessage: 'Set "xpack.reporting.roles.enabled: false" in kibana.yml.', + }), + i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepTwo', { + defaultMessage: 'Remove "xpack.reporting.roles.allow" in kibana.yml, if present.', + }), + ] + : []), + i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepThree', { defaultMessage: - `Create one or more custom roles that provide Kibana application` + - ` privileges to reporting features in **Management > Security > Roles**.`, + 'Create one or more custom roles that provide Kibana application' + + ' privileges to reporting features in Management > Security > Roles.', }), i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepFour', { - defaultMessage: - 'Assign the custom role(s) as desired. You may remove the "{deprecatedRole}" role from the user(s) .', - values: { deprecatedRole: `reporting_user` }, + defaultMessage: 'Create a custom role with Kibana privileges to grant access to Reporting.', }), i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepFive', { defaultMessage: - 'Remove the role that grants Reporting privilege from all role mappings and add the custom role. The affected role mappings are: {roleMappings}.', + 'Remove the "reporting_user" role from all role mappings and add the custom role. The affected role mappings are: {roleMappings}.', values: { roleMappings }, }), ], From a72a5f61ad0745664914aac0052e3079c3926bfc Mon Sep 17 00:00:00 2001 From: Timothy Sullivan Date: Wed, 20 Oct 2021 11:54:46 -0700 Subject: [PATCH 3/6] updates per feedback --- .../reporting/server/deprecations/reporting_role.test.ts | 4 ++-- .../plugins/reporting/server/deprecations/reporting_role.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts b/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts index da08ea8e091c4..1c104bad72103 100644 --- a/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts +++ b/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts @@ -85,7 +85,7 @@ describe('roles mapped to a deprecated role', () => { }); describe('check deprecations when security is disabled', () => { - test('logs no deprecations: roles enabled', async () => { + test('logs no deprecations: roles not enabled', async () => { const mockReportingConfig = createMockConfigSchema({ roles: { enabled: false } }); reportingCore = await createMockReportingCore( mockReportingConfig, @@ -94,7 +94,7 @@ describe('check deprecations when security is disabled', () => { expect(await getDeprecationsInfo(context, { reportingCore })).toMatchInlineSnapshot(`Array []`); }); - test('logs no deprecations: roles not enabled', async () => { + test('logs no deprecations: roles enabled', async () => { const mockReportingConfig = createMockConfigSchema(); // roles.enabled: true is default in 7.x / 8.0 reportingCore = await createMockReportingCore( mockReportingConfig, diff --git a/x-pack/plugins/reporting/server/deprecations/reporting_role.ts b/x-pack/plugins/reporting/server/deprecations/reporting_role.ts index 18df3c583555b..f83854459c2c3 100644 --- a/x-pack/plugins/reporting/server/deprecations/reporting_role.ts +++ b/x-pack/plugins/reporting/server/deprecations/reporting_role.ts @@ -33,7 +33,7 @@ export async function getDeprecationsInfo( const { security } = reportingCore.getPluginSetupDeps(); // Nothing to do if security is disabled - if (!security) { + if (!security?.license.isEnabled()) { return []; } From f8be2107495a7467698c915b37f29bb4bb4f90e2 Mon Sep 17 00:00:00 2001 From: Timothy Sullivan Date: Wed, 20 Oct 2021 12:00:06 -0700 Subject: [PATCH 4/6] store packageInfo in reportingCore --- x-pack/plugins/reporting/server/core.ts | 8 ++++---- x-pack/plugins/reporting/server/routes/generate/legacy.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/reporting/server/core.ts b/x-pack/plugins/reporting/server/core.ts index a4986acc0253b..38a1ca140fcad 100644 --- a/x-pack/plugins/reporting/server/core.ts +++ b/x-pack/plugins/reporting/server/core.ts @@ -13,6 +13,7 @@ import { BasePath, IClusterClient, KibanaRequest, + PackageInfo, PluginInitializerContext, SavedObjectsClientContract, SavedObjectsServiceStart, @@ -57,7 +58,7 @@ export interface ReportingInternalStart { } export class ReportingCore { - private kibanaVersion: string; + private packageInfo: PackageInfo; private pluginSetupDeps?: ReportingInternalSetup; private pluginStartDeps?: ReportingInternalStart; private readonly pluginSetup$ = new Rx.ReplaySubject(); // observe async background setupDeps and config each are done @@ -72,8 +73,7 @@ export class ReportingCore { public getContract: () => ReportingSetup; constructor(private logger: LevelLogger, context: PluginInitializerContext) { - // TODO: capture the entire packageInfo so we can form documentation links on the server - this.kibanaVersion = context.env.packageInfo.version; + this.packageInfo = context.env.packageInfo; const syncConfig = context.config.get(); this.deprecatedAllowedRoles = syncConfig.roles.enabled ? syncConfig.roles.allow : false; this.executeTask = new ExecuteReportTask(this, syncConfig, this.logger); @@ -87,7 +87,7 @@ export class ReportingCore { } public getKibanaVersion() { - return this.kibanaVersion; + return this.packageInfo; } /* diff --git a/x-pack/plugins/reporting/server/routes/generate/legacy.ts b/x-pack/plugins/reporting/server/routes/generate/legacy.ts index 92f1784dc8eca..53c0fbf3b7bb6 100644 --- a/x-pack/plugins/reporting/server/routes/generate/legacy.ts +++ b/x-pack/plugins/reporting/server/routes/generate/legacy.ts @@ -53,7 +53,7 @@ export function registerLegacy(reporting: ReportingCore, logger: LevelLogger) { savedObjectId, browserTimezone, queryString, - version: reporting.getKibanaVersion(), + version: reporting.getKibanaVersion().version, }); } catch (err) { throw requestHandler.handleError(err); From f61cd48c383c5ca0cad6d807c9cca83319b9d71e Mon Sep 17 00:00:00 2001 From: Timothy Sullivan Date: Wed, 20 Oct 2021 12:04:32 -0700 Subject: [PATCH 5/6] use branch in the documentation links generated in the server --- x-pack/plugins/reporting/server/core.ts | 2 +- .../reporting/server/deprecations/reporting_role.ts | 7 ++++--- x-pack/plugins/reporting/server/routes/generate/legacy.ts | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/reporting/server/core.ts b/x-pack/plugins/reporting/server/core.ts index 38a1ca140fcad..6b00e08c58685 100644 --- a/x-pack/plugins/reporting/server/core.ts +++ b/x-pack/plugins/reporting/server/core.ts @@ -86,7 +86,7 @@ export class ReportingCore { this.executing = new Set(); } - public getKibanaVersion() { + public getKibanaPackageInfo() { return this.packageInfo; } diff --git a/x-pack/plugins/reporting/server/deprecations/reporting_role.ts b/x-pack/plugins/reporting/server/deprecations/reporting_role.ts index f83854459c2c3..f9323c13cc67b 100644 --- a/x-pack/plugins/reporting/server/deprecations/reporting_role.ts +++ b/x-pack/plugins/reporting/server/deprecations/reporting_role.ts @@ -19,7 +19,8 @@ import { ReportingCore } from '../'; import { deprecations } from '../lib/deprecations'; const REPORTING_USER_ROLE_NAME = 'reporting_user'; -const DOCUMENTATION_URL = 'https://www.elastic.co/guide/en/kibana/current/kibana-privileges.html'; +const getDocumentationUrl = (branch: string) => + `https://www.elastic.co/guide/en/kibana/${branch}/kibana-privileges.html`; interface ExtraDependencies { reportingCore: ReportingCore; @@ -120,7 +121,7 @@ async function getUsersDeprecations( correctiveActions: { manualSteps: strings.manualSteps(reportingUsers.join(', ')) }, level: 'warning', deprecationType: 'feature', - documentationUrl: DOCUMENTATION_URL, + documentationUrl: getDocumentationUrl(reportingCore.getKibanaPackageInfo().branch), }, ]; } @@ -208,7 +209,7 @@ async function getRoleMappingsDeprecations( }, level: 'warning', deprecationType: 'feature', - documentationUrl: DOCUMENTATION_URL, + documentationUrl: getDocumentationUrl(reportingCore.getKibanaPackageInfo().branch), }, ]; } diff --git a/x-pack/plugins/reporting/server/routes/generate/legacy.ts b/x-pack/plugins/reporting/server/routes/generate/legacy.ts index 53c0fbf3b7bb6..f262d186d5531 100644 --- a/x-pack/plugins/reporting/server/routes/generate/legacy.ts +++ b/x-pack/plugins/reporting/server/routes/generate/legacy.ts @@ -53,7 +53,7 @@ export function registerLegacy(reporting: ReportingCore, logger: LevelLogger) { savedObjectId, browserTimezone, queryString, - version: reporting.getKibanaVersion().version, + version: reporting.getKibanaPackageInfo().version, }); } catch (err) { throw requestHandler.handleError(err); From 7bb8efad6a7c569209997843119de640be33866b Mon Sep 17 00:00:00 2001 From: Timothy Sullivan Date: Wed, 20 Oct 2021 12:05:41 -0700 Subject: [PATCH 6/6] add tests for scenario where config does not need to be changed --- .../__snapshots__/reporting_role.test.ts.snap | 54 ++++++++++++++----- .../deprecations/reporting_role.test.ts | 42 +++++++++++---- .../server/deprecations/reporting_role.ts | 7 +-- 3 files changed, 75 insertions(+), 28 deletions(-) diff --git a/x-pack/plugins/reporting/server/deprecations/__snapshots__/reporting_role.test.ts.snap b/x-pack/plugins/reporting/server/deprecations/__snapshots__/reporting_role.test.ts.snap index 5afed2c4c4e1f..00a2a63280c9e 100644 --- a/x-pack/plugins/reporting/server/deprecations/__snapshots__/reporting_role.test.ts.snap +++ b/x-pack/plugins/reporting/server/deprecations/__snapshots__/reporting_role.test.ts.snap @@ -1,19 +1,36 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`roles mapped to a deprecated role logs a deprecation when a role was found that maps to a deprecated custom role from the roles.allow setting 1`] = ` +exports[`roles mapped to a deprecated role includes steps to remove the incompatible config, when applicable 1`] = ` Array [ Object { "correctiveActions": Object { "manualSteps": Array [ "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml.", "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml, if present.", - "Create one or more custom roles that provide Kibana application privileges to reporting features in Management > Security > Roles.", + "Create a custom role with Kibana privileges to grant access to Reporting.", + "Remove the \\"reporting_user\\" role from all users and add the custom role. The affected users are: reportron[reporting_user].", + ], + }, + "deprecationType": "feature", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/branch/kibana-privileges.html", + "level": "warning", + "message": "Existing users have their Reporting privilege granted by a deprecated setting.", + "title": "The \\"reporting_user\\" role is deprecated: check user roles", + }, +] +`; + +exports[`roles mapped to a deprecated role logs a deprecation when a role was found that maps to a deprecated custom role from the roles.allow setting 1`] = ` +Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ "Create a custom role with Kibana privileges to grant access to Reporting.", "Remove the \\"reporting_user\\" role from all role mappings and add the custom role. The affected role mappings are: dungeon_master[my_test_reporting_user].", ], }, "deprecationType": "feature", - "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/kibana-privileges.html", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/branch/kibana-privileges.html", "level": "warning", "message": "Existing roles are mapped to a deprecated role for Reporting privileges", "title": "The \\"reporting_user\\" role is deprecated: check role mappings", @@ -26,15 +43,12 @@ Array [ Object { "correctiveActions": Object { "manualSteps": Array [ - "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml.", - "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml, if present.", - "Create one or more custom roles that provide Kibana application privileges to reporting features in Management > Security > Roles.", "Create a custom role with Kibana privileges to grant access to Reporting.", "Remove the \\"reporting_user\\" role from all role mappings and add the custom role. The affected role mappings are: dungeon_master[reporting_user].", ], }, "deprecationType": "feature", - "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/kibana-privileges.html", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/branch/kibana-privileges.html", "level": "warning", "message": "Existing roles are mapped to a deprecated role for Reporting privileges", "title": "The \\"reporting_user\\" role is deprecated: check role mappings", @@ -42,19 +56,37 @@ Array [ ] `; -exports[`users assigned to a deprecated role logs a deprecation when a user was found with a deprecated custom role from the roles.allow setting 1`] = ` +exports[`users assigned to a deprecated role includes steps to remove the incompatible config, when applicable 1`] = ` Array [ Object { "correctiveActions": Object { "manualSteps": Array [ "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml.", "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml, if present.", + "Create a custom role with Kibana privileges to grant access to Reporting.", + "Remove the \\"reporting_user\\" role from all users and add the custom role. The affected users are: reportron[reporting_user].", + ], + }, + "deprecationType": "feature", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/branch/kibana-privileges.html", + "level": "warning", + "message": "Existing users have their Reporting privilege granted by a deprecated setting.", + "title": "The \\"reporting_user\\" role is deprecated: check user roles", + }, +] +`; + +exports[`users assigned to a deprecated role logs a deprecation when a user was found with a deprecated custom role from the roles.allow setting 1`] = ` +Array [ + Object { + "correctiveActions": Object { + "manualSteps": Array [ "Create a custom role with Kibana privileges to grant access to Reporting.", "Remove the \\"reporting_user\\" role from all users and add the custom role. The affected users are: reportron[my_test_reporting_user].", ], }, "deprecationType": "feature", - "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/kibana-privileges.html", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/branch/kibana-privileges.html", "level": "warning", "message": "Existing users have their Reporting privilege granted by a deprecated setting.", "title": "The \\"reporting_user\\" role is deprecated: check user roles", @@ -67,14 +99,12 @@ Array [ Object { "correctiveActions": Object { "manualSteps": Array [ - "Set \\"xpack.reporting.roles.enabled: false\\" in kibana.yml.", - "Remove \\"xpack.reporting.roles.allow\\" in kibana.yml, if present.", "Create a custom role with Kibana privileges to grant access to Reporting.", "Remove the \\"reporting_user\\" role from all users and add the custom role. The affected users are: reportron[reporting_user].", ], }, "deprecationType": "feature", - "documentationUrl": "https://www.elastic.co/guide/en/kibana/current/kibana-privileges.html", + "documentationUrl": "https://www.elastic.co/guide/en/kibana/branch/kibana-privileges.html", "level": "warning", "message": "Existing users have their Reporting privilege granted by a deprecated setting.", "title": "The \\"reporting_user\\" role is deprecated: check user roles", diff --git a/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts b/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts index 1c104bad72103..2286a9767f000 100644 --- a/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts +++ b/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts @@ -20,8 +20,9 @@ let context: GetDeprecationsContext; let esClient: jest.Mocked; beforeEach(async () => { - const mockReportingConfig = createMockConfigSchema({ roles: { enabled: false } }); - reportingCore = await createMockReportingCore(mockReportingConfig); + reportingCore = await createMockReportingCore( + createMockConfigSchema({ roles: { enabled: false } }) + ); esClient = elasticsearchServiceMock.createScopedClusterClient(); esClient.asCurrentUser.security.getUser = jest.fn().mockResolvedValue({ @@ -40,15 +41,14 @@ describe('users assigned to a deprecated role', () => { body: { reportron: { username: 'reportron', roles: ['kibana_admin', 'reporting_user'] } }, }); - const mockReportingConfig = createMockConfigSchema({ roles: { enabled: true } }); - reportingCore = await createMockReportingCore(mockReportingConfig); + reportingCore = await createMockReportingCore(createMockConfigSchema()); expect(await getDeprecationsInfo(context, { reportingCore })).toMatchSnapshot(); }); test('logs a deprecation when a user was found with a deprecated custom role from the roles.allow setting', async () => { reportingCore = await createMockReportingCore( - createMockConfigSchema({ roles: { enabled: true, allow: ['my_test_reporting_user'] } }) + createMockConfigSchema({ roles: { allow: ['my_test_reporting_user'] } }) ); esClient.asCurrentUser.security.getUser = jest.fn().mockResolvedValue({ body: { @@ -58,6 +58,18 @@ describe('users assigned to a deprecated role', () => { expect(await getDeprecationsInfo(context, { reportingCore })).toMatchSnapshot(); }); + + test('includes steps to remove the incompatible config, when applicable', async () => { + esClient.asCurrentUser.security.getUser = jest.fn().mockResolvedValue({ + body: { reportron: { username: 'reportron', roles: ['kibana_admin', 'reporting_user'] } }, + }); + + reportingCore = await createMockReportingCore( + createMockConfigSchema({ roles: { enabled: true } }) + ); + + expect(await getDeprecationsInfo(context, { reportingCore })).toMatchSnapshot(); + }); }); describe('roles mapped to a deprecated role', () => { @@ -66,15 +78,14 @@ describe('roles mapped to a deprecated role', () => { body: { dungeon_master: { roles: ['reporting_user'] } }, }); - const mockReportingConfig = createMockConfigSchema({ roles: { enabled: true } }); - reportingCore = await createMockReportingCore(mockReportingConfig); + reportingCore = await createMockReportingCore(createMockConfigSchema()); expect(await getDeprecationsInfo(context, { reportingCore })).toMatchSnapshot(); }); test('logs a deprecation when a role was found that maps to a deprecated custom role from the roles.allow setting', async () => { reportingCore = await createMockReportingCore( - createMockConfigSchema({ roles: { enabled: true, allow: ['my_test_reporting_user'] } }) + createMockConfigSchema({ roles: { allow: ['my_test_reporting_user'] } }) ); esClient.asCurrentUser.security.getRoleMapping = jest.fn().mockResolvedValue({ body: { dungeon_master: { roles: ['my_test_reporting_user'] } }, @@ -82,13 +93,24 @@ describe('roles mapped to a deprecated role', () => { expect(await getDeprecationsInfo(context, { reportingCore })).toMatchSnapshot(); }); + + test('includes steps to remove the incompatible config, when applicable', async () => { + esClient.asCurrentUser.security.getUser = jest.fn().mockResolvedValue({ + body: { reportron: { username: 'reportron', roles: ['kibana_admin', 'reporting_user'] } }, + }); + + reportingCore = await createMockReportingCore( + createMockConfigSchema({ roles: { enabled: true } }) + ); + + expect(await getDeprecationsInfo(context, { reportingCore })).toMatchSnapshot(); + }); }); describe('check deprecations when security is disabled', () => { test('logs no deprecations: roles not enabled', async () => { - const mockReportingConfig = createMockConfigSchema({ roles: { enabled: false } }); reportingCore = await createMockReportingCore( - mockReportingConfig, + createMockConfigSchema({ roles: { enabled: false } }), createMockPluginSetup({ security: null }) ); expect(await getDeprecationsInfo(context, { reportingCore })).toMatchInlineSnapshot(`Array []`); diff --git a/x-pack/plugins/reporting/server/deprecations/reporting_role.ts b/x-pack/plugins/reporting/server/deprecations/reporting_role.ts index f9323c13cc67b..a2a7e9c78726d 100644 --- a/x-pack/plugins/reporting/server/deprecations/reporting_role.ts +++ b/x-pack/plugins/reporting/server/deprecations/reporting_role.ts @@ -153,14 +153,9 @@ async function getRoleMappingsDeprecations( : []), i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepThree', { - defaultMessage: - 'Create one or more custom roles that provide Kibana application' + - ' privileges to reporting features in Management > Security > Roles.', - }), - i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepFour', { defaultMessage: 'Create a custom role with Kibana privileges to grant access to Reporting.', }), - i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepFive', { + i18n.translate('xpack.reporting.deprecations.reportingRoleMappings.manualStepFour', { defaultMessage: 'Remove the "reporting_user" role from all role mappings and add the custom role. The affected role mappings are: {roleMappings}.', values: { roleMappings },