Skip to content

Commit

Permalink
[Reporting] Add deprecation messages for roles mapped to reporting_user
Browse files Browse the repository at this point in the history
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
  • Loading branch information
tsullivan committed Oct 19, 2021
1 parent 63b9762 commit 4847e72
Show file tree
Hide file tree
Showing 10 changed files with 460 additions and 131 deletions.
2 changes: 1 addition & 1 deletion x-pack/plugins/reporting/server/config/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
]
`);
});
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/reporting/server/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const config: PluginConfigDescriptor<ReportingConfigType> = {
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 },
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/reporting/server/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export class ReportingCore {
public getContract: () => ReportingSetup;

constructor(private logger: LevelLogger, context: PluginInitializerContext<ReportingConfigType>) {
// 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<ReportingConfigType>();
this.deprecatedAllowedRoles = syncConfig.roles.enabled ? syncConfig.roles.allow : false;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

165 changes: 93 additions & 72 deletions x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -18,6 +22,7 @@ let esClient: jest.Mocked<IScopedClusterClient>;
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'] } },
Expand All @@ -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",
},
]
`);
Expand Down
Loading

0 comments on commit 4847e72

Please sign in to comment.