Skip to content

Commit

Permalink
[Reporting] Use Kibana feature privileges only to control access to r…
Browse files Browse the repository at this point in the history
…eporting (elastic#200834)

## Summary

This PR discontinues Reporting from having dual models for determining
the privilege to generate a report, and uses Kibana feature privileges
as the single model that controls those privileges.

### Changes
1. Removes all logic that is based on following settings:
    * `xpack.reporting.roles.enabled`
    * `xpack.reporting.roles.allow`
The settings are still supported, but any features that use the settings
are removed.
2. Removes the detection of the settings from the Upgrade Assistant
integration

### Release note
The default system of granting users the privilege to generate reports
has changed. Rather than assigning users the `reporting_user` role,
administrators should create a custom role that grants report-creation
privileges using Kibana application privileges.

### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.

- [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
- [x] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.

Correlates with https://elasticco.atlassian.net/browse/ES-9856: assign
the built-in `reporting_user` role the necessary Kibana application
privileges, and make the role not marked as deprecated.

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
2 people authored and CAWilson94 committed Dec 9, 2024
1 parent 9701ad4 commit ec96f00
Show file tree
Hide file tree
Showing 64 changed files with 140 additions and 1,319 deletions.
1 change: 0 additions & 1 deletion .buildkite/ftr_platform_stateful_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,6 @@ enabled:
- x-pack/test/plugin_functional/config.ts
- x-pack/test/reporting_api_integration/reporting_and_security.config.ts
- x-pack/test/reporting_api_integration/reporting_without_security.config.ts
- x-pack/test/reporting_functional/reporting_and_deprecated_security.config.ts
- x-pack/test/reporting_functional/reporting_and_security.config.ts
- x-pack/test/reporting_functional/reporting_without_security.config.ts
- x-pack/test/rule_registry/security_and_spaces/config_basic.ts
Expand Down
1 change: 0 additions & 1 deletion config/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ xpack.task_manager.metrics_reset_interval: 120000
# Reporting feature
xpack.screenshotting.enabled: false
xpack.reporting.queue.pollInterval: 3m
xpack.reporting.roles.enabled: false
xpack.reporting.statefulSettings.enabled: false
xpack.reporting.csv.maxConcurrentShardRequests: 0

Expand Down
25 changes: 2 additions & 23 deletions docs/settings/reporting-settings.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -61,29 +61,8 @@ xpack.reporting.encryptionKey: "something_secret"
[[reporting-advanced-settings]]
=== Security settings

Reporting has two forms of access control: each user can only access their own reports,
and custom roles determine who has the privilege to generate reports. When Reporting is configured with
<<kibana-privileges, {kib} application privileges>>, you can control the spaces and applications where users
are allowed to generate reports.

[NOTE]
============================================================================
The `xpack.reporting.roles` settings are for a deprecated system of access control in Reporting. Turning off
this feature allows API keys to generate reports, and allows reporting access through {kib} application
privileges. We recommend that you explicitly turn off reporting's deprecated access control feature by adding
`xpack.reporting.roles.enabled: false` to kibana.yml. This will enable you to create custom roles that provide
application privileges for reporting, as described in <<grant-user-access, granting users access to
reporting>>.
============================================================================

[[xpack-reporting-roles-enabled]] `xpack.reporting.roles.enabled`::
deprecated:[7.14.0,The default for this setting will be `false` in an upcoming version of {kib}.] Sets access
control to a set of assigned reporting roles, specified by `xpack.reporting.roles.allow`. Defaults to `true`.

`xpack.reporting.roles.allow`::
deprecated:[7.14.0] In addition to superusers, specifies the roles that can generate reports using the
{ref}/security-api.html#security-role-apis[{es} role management APIs]. Requires `xpack.reporting.roles.enabled`
to be `true`. Defaults to `[ "reporting_user" ]`.
Reporting privileges are configured with <<kibana-privileges, {kib} application privileges>>. You can control
the spaces and applications where users are allowed to generate reports.

[float]
[[reporting-job-queue-settings]]
Expand Down
13 changes: 2 additions & 11 deletions docs/setup/configuring-reporting.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,6 @@ to enable the {kib} server to have screenshotting capabilities.
=== Grant users access to reporting
When security is enabled, you grant users access to {report-features} with <<kibana-privileges, {kib} application privileges>>, which allow you to create custom roles that control the spaces and applications where users generate reports.

. Enable application privileges in Reporting. To enable, turn off the default user access control features in `kibana.yml`:
+
[source,yaml]
------------------------------------
xpack.reporting.roles.enabled: false
------------------------------------
+
NOTE: If you use the default settings, you can still create a custom role that grants reporting privileges. The default role is `reporting_user`. This behavior is being deprecated and does not allow application-level access controls for {report-features}, and does not allow API keys or authentication tokens to authorize report generation. Refer to <<reporting-advanced-settings, reporting security settings>> for information and caveats about the deprecated access control features.

. Create the reporting role.

.. Go to the *Roles* management page using the navigation menu or the
Expand Down Expand Up @@ -79,7 +70,7 @@ NOTE: If you have a Basic license, sub-feature privileges are unavailable. For d
[role="screenshot"]
image::user/reporting/images/kibana-privileges-with-reporting.png["Kibana privileges with Reporting options, Gold or higher license"]
+
NOTE: If the *Reporting* options for application features are unavailable, and the cluster license is higher than Basic, contact your administrator, or <<reporting-advanced-settings,check that `xpack.reporting.roles.enabled` is set to `false` in kibana.yml>>.
NOTE: If the *Reporting* options for application features are unavailable, and the cluster license is higher than Basic, contact your administrator.

.. Click *Add {kib} privilege*.

Expand All @@ -101,7 +92,7 @@ Granting the privilege to generate reports also grants the user the privilege to
[float]
[[reporting-roles-user-api]]
==== Grant access with the role API
With <<grant-user-access,{kib} application privileges>> enabled in Reporting, you can also use the {api-kibana}/group/endpoint-roles[role APIs] to grant access to the {report-features}, using *All* privileges, or sub-feature privileges.
With <<grant-user-access,{kib} application privileges>>, you can use the {api-kibana}/group/endpoint-roles[role APIs] to grant access to the {report-features}, using *All* privileges, or sub-feature privileges.

NOTE: This API request needs to be run against the <<api,Kibana API endpoint>>.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ describe('GetCsvReportPanelAction', () => {
core,
apiClient,
startServices$: mockStartServices$,
usesUiCapabilities: true,
csvConfig,
});

Expand Down Expand Up @@ -154,7 +153,6 @@ describe('GetCsvReportPanelAction', () => {
core,
apiClient,
startServices$: mockStartServices$,
usesUiCapabilities: true,
csvConfig,
});

Expand All @@ -177,7 +175,6 @@ describe('GetCsvReportPanelAction', () => {
core,
apiClient,
startServices$: mockStartServices$,
usesUiCapabilities: true,
csvConfig,
});

Expand All @@ -197,7 +194,6 @@ describe('GetCsvReportPanelAction', () => {
core,
apiClient,
startServices$: mockStartServices$,
usesUiCapabilities: true,
csvConfig,
});

Expand All @@ -219,7 +215,6 @@ describe('GetCsvReportPanelAction', () => {
core,
apiClient,
startServices$: mockStartServices$,
usesUiCapabilities: true,
csvConfig,
});

Expand All @@ -232,7 +227,6 @@ describe('GetCsvReportPanelAction', () => {
core,
apiClient,
startServices$: mockStartServices$,
usesUiCapabilities: true,
csvConfig,
});

Expand All @@ -249,7 +243,6 @@ describe('GetCsvReportPanelAction', () => {
core,
apiClient,
startServices$: mockStartServices$,
usesUiCapabilities: true,
csvConfig,
});

Expand All @@ -263,25 +256,12 @@ describe('GetCsvReportPanelAction', () => {
core,
apiClient,
startServices$: mockStartServices$,
usesUiCapabilities: true,
csvConfig,
});

await Rx.firstValueFrom(mockStartServices$);

expect(await plugin.isCompatible(context)).toEqual(true);
});

it(`allows csv generation when license is valid and deprecated roles config is enabled`, async () => {
const plugin = new ReportingCsvPanelAction({
core,
apiClient,
startServices$: mockStartServices$,
usesUiCapabilities: false,
csvConfig,
});

expect(await plugin.isCompatible(context)).toEqual(true);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ interface Params {
csvConfig: ClientConfigType['csv'];
core: CoreSetup;
startServices$: Observable<StartServices>;
usesUiCapabilities: boolean;
}

interface ExecutionParams {
Expand Down Expand Up @@ -104,15 +103,13 @@ export class ReportingCsvPanelAction implements ActionDefinition<EmbeddableApiCo
private readonly apiClient: ReportingAPIClient;
private readonly theme: ThemeServiceSetup;
private readonly startServices$: Params['startServices$'];
private readonly usesUiCapabilities: boolean;

constructor({ core, csvConfig, apiClient, startServices$, usesUiCapabilities }: Params) {
constructor({ core, apiClient, startServices$ }: Params) {
this.isDownloading = false;
this.apiClient = apiClient;
this.notifications = core.notifications;
this.theme = core.theme;
this.startServices$ = startServices$;
this.usesUiCapabilities = usesUiCapabilities;
this.i18nStrings = getI18nStrings(apiClient);
}

Expand Down Expand Up @@ -142,10 +139,7 @@ export class ReportingCsvPanelAction implements ActionDefinition<EmbeddableApiCo
const licenseHasCsvReporting = checkLicense(license.check('reporting', 'basic')).showLinks;

// NOTE: For historical reasons capability identifier is called `downloadCsv. It can not be renamed.
const capabilityHasCsvReporting = this.usesUiCapabilities
? application.capabilities.dashboard?.downloadCsv === true
: true; // if we're using the deprecated "xpack.reporting.roles.enabled=true" setting, the panel action is always visible

const capabilityHasCsvReporting = application.capabilities.dashboard?.downloadCsv === true;
if (!licenseHasCsvReporting || !capabilityHasCsvReporting) {
return false;
}
Expand Down
4 changes: 0 additions & 4 deletions packages/kbn-reporting/mocks_server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ export const createMockConfigSchema = (
scroll: { size: 500, duration: '30s' },
...overrides.csv,
},
roles: {
enabled: false,
...overrides.roles,
},
capture: { maxAttempts: 1 },
export_types: {
pdf: { enabled: true },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,13 @@ export type StartServices = [

export interface ExportModalShareOpts {
apiClient: ReportingAPIClient;
usesUiCapabilities: boolean;
license: ILicense;
application: ApplicationStart;
startServices$: Rx.Observable<StartServices>;
}

export interface ExportPanelShareOpts {
apiClient: ReportingAPIClient;
usesUiCapabilities: boolean;
license: ILicense;
application: ApplicationStart;
startServices$: Rx.Observable<StartServices>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export const reportingCsvShareProvider = ({
apiClient,
application,
license,
usesUiCapabilities,
startServices$,
}: ExportModalShareOpts) => {
const getShareMenuItems = ({ objectType, sharingData, toasts }: ShareContext) => {
Expand Down Expand Up @@ -76,12 +75,7 @@ export const reportingCsvShareProvider = ({
const licenseHasCsvReporting = licenseCheck.showLinks;
const licenseDisabled = !licenseCheck.enableLinks;

let capabilityHasCsvReporting = false;
if (usesUiCapabilities) {
capabilityHasCsvReporting = application.capabilities.discover?.generateCsv === true;
} else {
capabilityHasCsvReporting = true; // deprecated
}
const capabilityHasCsvReporting = application.capabilities.discover?.generateCsv === true;

const generateReportingJobCSV = ({ intl }: { intl: InjectedIntl }) => {
const decoratedJobParams = apiClient.getDecoratedJobParams(getJobParams());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export const reportingExportModalProvider = ({
apiClient,
license,
application,
usesUiCapabilities,
startServices$,
}: ExportModalShareOpts): ShareMenuProvider => {
const getShareMenuItems = ({
Expand All @@ -64,18 +63,10 @@ export const reportingExportModalProvider = ({
const licenseHasScreenshotReporting = showLinks;
const licenseDisabled = !enableLinks;

let capabilityHasDashboardScreenshotReporting = false;
let capabilityHasVisualizeScreenshotReporting = false;
if (usesUiCapabilities) {
capabilityHasDashboardScreenshotReporting =
application.capabilities.dashboard?.generateScreenshot === true;
capabilityHasVisualizeScreenshotReporting =
application.capabilities.visualize?.generateScreenshot === true;
} else {
// deprecated
capabilityHasDashboardScreenshotReporting = true;
capabilityHasVisualizeScreenshotReporting = true;
}
const capabilityHasDashboardScreenshotReporting =
application.capabilities.dashboard?.generateScreenshot === true;
const capabilityHasVisualizeScreenshotReporting =
application.capabilities.visualize?.generateScreenshot === true;

if (!licenseHasScreenshotReporting) {
return [];
Expand Down
1 change: 0 additions & 1 deletion packages/kbn-reporting/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export interface ClientConfigType {
intervalErrorMultiplier: number;
};
};
roles: { enabled: boolean };
export_types: {
pdf: { enabled: boolean };
png: { enabled: boolean };
Expand Down

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

10 changes: 0 additions & 10 deletions packages/kbn-reporting/server/config_schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,4 @@ describe('Reporting Config Schema', () => {
ConfigSchema.validate({ export_types: { csv: { enabled: true } } }, { dev: true })
).not.toThrow();
});

describe('roles', () => {
it('should have roles enabled set to false for serverless by default', () => {
expect(ConfigSchema.validate({}, { serverless: true }).roles.enabled).toBe(false);
});

it('should have roles enabled set to true for non-serverless by default', () => {
expect(ConfigSchema.validate({}).roles.enabled).toBe(true);
});
});
});
16 changes: 6 additions & 10 deletions packages/kbn-reporting/server/config_schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,12 @@ const EncryptionKeySchema = schema.conditional(
schema.string({ defaultValue: 'a'.repeat(32) })
);

const RolesSchema = schema.object({
enabled: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
traditional: schema.boolean({ defaultValue: true }),
}), // true: use ES API for access control (deprecated in 7.x). false: use Kibana API for application features (8.0)
allow: offeringBasedSchema({
serverless: schema.arrayOf(schema.string(), { defaultValue: [] }),
traditional: schema.arrayOf(schema.string(), { defaultValue: ['reporting_user'] }),
}),
});
const RolesSchema = schema.maybe(
schema.object({
enabled: schema.boolean(),
allow: schema.arrayOf(schema.string()),
})
); // unused as of 9.0

// Browser side polling: job completion notifier, management table auto-refresh
// NOTE: can not use schema.duration, a bug prevents it being passed to the browser correctly
Expand Down
4 changes: 0 additions & 4 deletions packages/kbn-reporting/server/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ import type { ExportType } from './export_type';

export interface ReportingServerPluginSetup {
registerExportTypes: (item: ExportType) => void;
/**
* Used to inform plugins if Reporting config is compatible with UI Capabilities / Application Sub-Feature Controls
*/
usesUiCapabilities: () => boolean;
}

// standard type for create job function of any ExportType implementation
Expand Down
2 changes: 0 additions & 2 deletions test/plugin_functional/test_suites/core_plugins/rendering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,6 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
* NOTE: The Reporting plugin is currently disabled in functional tests (see test/functional/config.base.js).
* It will be re-enabled once #102552 is completed.
*/
// 'xpack.reporting.roles.allow (array)',
// 'xpack.reporting.roles.enabled (boolean)',
// 'xpack.reporting.poll.jobCompletionNotifier.interval (number)',
// 'xpack.reporting.poll.jobCompletionNotifier.intervalErrorMultiplier (number)',
// 'xpack.reporting.poll.jobsRefresh.interval (number)',
Expand Down
8 changes: 3 additions & 5 deletions x-pack/plugins/canvas/public/services/kibana_services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,9 @@ export const setKibanaServices = (
embeddableService = deps.embeddable;
expressionsService = deps.expressions;
presentationUtilService = deps.presentationUtil;
reportingService = Boolean(
deps.reporting?.usesUiCapabilities() && !kibanaCore.application.capabilities.canvas?.generatePdf
)
? undefined
: deps.reporting;
reportingService = Boolean(kibanaCore.application.capabilities.canvas?.generatePdf)
? deps.reporting
: undefined;
spacesService = deps.spaces;
uiActionsService = deps.uiActions;
visualizationsService = deps.visualizations;
Expand Down
Loading

0 comments on commit ec96f00

Please sign in to comment.