Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 24 additions & 24 deletions docs/developer/architecture/security/feature-registration.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@ Registering features also gives your plugin access to “UI Capabilities”. The

=== Registering a feature

Feature registration is controlled via the built-in `xpack_main` plugin. To register a feature, call `xpack_main`'s `registerFeature` function from your plugin's `init` function, and provide the appropriate details:
Feature registration is controlled via the built-in `features` plugin. To register a feature, call `features`'s `registerKibanaFeature` function from your plugin's `setup` lifecycle function, and provide the appropriate details:

["source","javascript"]
-----------
init(server) {
const xpackMainPlugin = server.plugins.xpack_main;
xpackMainPlugin.registerFeature({
setup(core, { features }) {
features.registerKibanaFeature({
// feature details here.
});
}
Expand Down Expand Up @@ -45,12 +44,12 @@ Registering a feature consists of the following fields. For more information, co
|An array of applications this feature enables. Typically, all of your plugin's apps (from `uiExports`) will be included here.

|`privileges` (required)
|{kib-repo}blob/{branch}/x-pack/plugins/features/common/feature.ts[`FeatureConfig`].
|{kib-repo}blob/{branch}/x-pack/plugins/features/common/feature.ts[`KibanaFeatureConfig`].
|See <<example-1-canvas,Example 1>> and <<example-2-dev-tools,Example 2>>
|The set of privileges this feature requires to function.

|`subFeatures` (optional)
|{kib-repo}blob/{branch}/x-pack/plugins/features/common/feature.ts[`FeatureConfig`].
|{kib-repo}blob/{branch}/x-pack/plugins/features/common/feature.ts[`KibanaFeatureConfig`].
|See <<example-3-discover,Example 3>>
|The set of subfeatures that enables finer access control than the `all` and `read` feature privileges. These options are only available in the Gold subscription level and higher.

Expand All @@ -73,25 +72,26 @@ For a full explanation of fields and options, consult the {kib-repo}blob/{branch
=== Using UI Capabilities

UI Capabilities are available to your public (client) plugin code. These capabilities are read-only, and are used to inform the UI. This object is namespaced by feature id. For example, if your feature id is “foo”, then your UI Capabilities are stored at `uiCapabilities.foo`.
To access capabilities, import them from `ui/capabilities`:
Capabilities can be accessed from your plugin's `start` lifecycle from the `core.application` service:

["source","javascript"]
-----------
import { uiCapabilities } from 'ui/capabilities';
public start(core) {
const { capabilities } = core.application;

const canUserSave = uiCapabilities.foo.save;
if (canUserSave) {
// show save button
const canUserSave = capabilities.foo.save;
if (canUserSave) {
// show save button
}
}
-----------

[[example-1-canvas]]
=== Example 1: Canvas Application
["source","javascript"]
-----------
init(server) {
const xpackMainPlugin = server.plugins.xpack_main;
xpackMainPlugin.registerFeature({
public setup(core, { features }) {
features.registerKibanaFeature({
id: 'canvas',
name: 'Canvas',
icon: 'canvasApp',
Expand Down Expand Up @@ -130,11 +130,13 @@ The `all` privilege defines a single “save” UI Capability. To access this in

["source","javascript"]
-----------
import { uiCapabilities } from 'ui/capabilities';
public start(core) {
const { capabilities } = core.application;

const canUserSave = uiCapabilities.canvas.save;
if (canUserSave) {
// show save button
const canUserSave = capabilities.canvas.save;
if (canUserSave) {
// show save button
}
}
-----------

Expand All @@ -145,9 +147,8 @@ Because the `read` privilege does not define the `save` capability, users with r

["source","javascript"]
-----------
init(server) {
const xpackMainPlugin = server.plugins.xpack_main;
xpackMainPlugin.registerFeature({
public setup(core, { features }) {
features.registerKibanaFeature({
id: 'dev_tools',
name: i18n.translate('xpack.features.devToolsFeatureName', {
defaultMessage: 'Dev Tools',
Expand Down Expand Up @@ -206,9 +207,8 @@ a single "Create Short URLs" subfeature privilege is defined, which allows users

["source","javascript"]
-----------
init(server) {
const xpackMainPlugin = server.plugins.xpack_main;
xpackMainPlugin.registerFeature({
public setup(core, { features }) {
features.registerKibanaFeature({
{
id: 'discover',
name: i18n.translate('xpack.features.discoverFeatureName', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,10 @@ created index. For more information, see {ref}/indices-templates.html[Index temp
* *Delete a policy.* You can’t delete a policy that is currently in use or
recover a deleted index.

[float]
=== Required permissions

The `manage_ilm` cluster privilege is required to access *Index lifecycle policies*.

You can add these privileges in *Stack Management > Security > Roles*.

7 changes: 7 additions & 0 deletions docs/management/managing-ccr.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ image::images/cross-cluster-replication-list-view.png[][Cross-cluster replicatio
* The Elasticsearch version of the local cluster must be the same as or newer than the remote cluster.
Refer to {ref}/ccr-overview.html[this document] for more information.

[float]
=== Required permissions

The `manage` and `manage_ccr` cluster privileges are required to access *Cross-Cluster Replication*.

You can add these privileges in *Stack Management > Security > Roles*.

[float]
[[configure-replication]]
=== Configure replication
Expand Down
7 changes: 7 additions & 0 deletions docs/management/managing-licenses.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ See {ref}/encrypting-communications.html[Encrypting communications].
{kib} and the {ref}/start-basic.html[start basic API] provide a list of all of
the features that will no longer be supported if you revert to a basic license.

[float]
=== Required permissions

The `manage` cluster privilege is required to access *License Management*.

You can add this privilege in *Stack Management > Security > Roles*.

[discrete]
[[update-license]]
=== Update your license
Expand Down
7 changes: 7 additions & 0 deletions docs/management/managing-remote-clusters.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ To get started, open the menu, then go to *Stack Management > Data > Remote Clus
[role="screenshot"]
image::images/remote-clusters-list-view.png[Remote Clusters list view, including Add a remote cluster button]

[float]
=== Required permissions

The `manage` cluster privilege is required to access *Remote Clusters*.

You can add this privilege in *Stack Management > Security > Roles*.

[float]
[[managing-remote-clusters]]
=== Add a remote cluster
Expand Down
7 changes: 7 additions & 0 deletions docs/management/rollups/create_and_manage_rollups.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ image::images/management_rollup_list.png[][List of currently active rollup jobs]
Before using this feature, you should be familiar with how rollups work.
{ref}/xpack-rollup.html[Rolling up historical data] is a good source for more detailed information.

[float]
=== Required permissions

The `manage_rollup` cluster privilege is required to access *Rollup jobs*.

You can add this privilege in *Stack Management > Security > Roles*.

[float]
[[create-and-manage-rollup-job]]
=== Create a rollup job
Expand Down
8 changes: 8 additions & 0 deletions docs/management/upgrade-assistant/index.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ Before you upgrade, make sure that you are using the latest released minor
version of {es} to see the most up-to-date deprecation issues.
For example, if you want to upgrade to to 7.0, make sure that you are using 6.8.

[float]
=== Required permissions

The `manage` cluster privilege is required to access the *Upgrade assistant*.
Additional privileges may be needed to perform certain actions.

You can add this privilege in *Stack Management > Security > Roles*.

[float]
=== Reindexing

Expand Down
2 changes: 1 addition & 1 deletion examples/alerting_example/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class AlertingExamplePlugin implements Plugin<void, void, AlertingExample
alerts.registerType(alwaysFiringAlert);
alerts.registerType(peopleInSpaceAlert);

features.registerFeature({
features.registerKibanaFeature({
id: ALERTING_EXAMPLE_APP_ID,
name: i18n.translate('alertsExample.featureRegistry.alertsExampleFeatureName', {
defaultMessage: 'Alerts Example',
Expand Down
2 changes: 1 addition & 1 deletion src/core/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -1283,7 +1283,7 @@ _See also: [Server's CoreSetup API Docs](/docs/development/core/server/kibana-pl
##### Plugin services
| Legacy Platform | New Platform | Notes |
| ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ----- |
| `server.plugins.xpack_main.registerFeature` | [`plugins.features.registerFeature`](x-pack/plugins/features/server/plugin.ts) | |
| `server.plugins.xpack_main.registerFeature` | [`plugins.features.registerKibanaFeature`](x-pack/plugins/features/server/plugin.ts) | |
| `server.plugins.xpack_main.feature(pluginID).registerLicenseCheckResultsGenerator` | [`x-pack licensing plugin`](/x-pack/plugins/licensing/README.md) | |

#### UI Exports
Expand Down
20 changes: 20 additions & 0 deletions src/plugins/management/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

import { i18n } from '@kbn/i18n';
import { BehaviorSubject } from 'rxjs';
import { ManagementSetup, ManagementStart } from './types';
import { FeatureCatalogueCategory, HomePublicPluginSetup } from '../../home/public';
import {
Expand All @@ -27,6 +28,9 @@ import {
DEFAULT_APP_CATEGORIES,
PluginInitializerContext,
AppMountParameters,
AppUpdater,
AppStatus,
AppNavLinkStatus,
} from '../../../core/public';

import {
Expand All @@ -41,6 +45,8 @@ interface ManagementSetupDependencies {
export class ManagementPlugin implements Plugin<ManagementSetup, ManagementStart> {
private readonly managementSections = new ManagementSectionsService();

private readonly appUpdater = new BehaviorSubject<AppUpdater>(() => ({}));

constructor(private initializerContext: PluginInitializerContext) {}

public setup(core: CoreSetup, { home }: ManagementSetupDependencies) {
Expand Down Expand Up @@ -70,6 +76,7 @@ export class ManagementPlugin implements Plugin<ManagementSetup, ManagementStart
order: 9040,
euiIconType: 'managementApp',
category: DEFAULT_APP_CATEGORIES.management,
updater$: this.appUpdater,
async mount(params: AppMountParameters) {
const { renderApp } = await import('./application');
const [coreStart] = await core.getStartServices();
Expand All @@ -89,6 +96,19 @@ export class ManagementPlugin implements Plugin<ManagementSetup, ManagementStart

public start(core: CoreStart) {
this.managementSections.start({ capabilities: core.application.capabilities });
const hasAnyEnabledApps = getSectionsServiceStartPrivate()
.getSectionsEnabled()
.some((section) => section.getAppsEnabled().length > 0);

if (!hasAnyEnabledApps) {
this.appUpdater.next(() => {
return {
status: AppStatus.inaccessible,
navLinkStatus: AppNavLinkStatus.hidden,
};
});
}

return {};
}
}
4 changes: 2 additions & 2 deletions test/common/services/security/test_user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ export async function createTestUserService(
}

return new (class TestUser {
async restoreDefaults() {
async restoreDefaults(shouldRefreshBrowser: boolean = true) {
if (isEnabled()) {
await this.setRoles(config.get('security.defaultRoles'));
await this.setRoles(config.get('security.defaultRoles'), shouldRefreshBrowser);
}
}

Expand Down
2 changes: 2 additions & 0 deletions test/functional/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { FilterBarProvider } from './filter_bar';
import { FlyoutProvider } from './flyout';
import { GlobalNavProvider } from './global_nav';
import { InspectorProvider } from './inspector';
import { ManagementMenuProvider } from './management';
import { QueryBarProvider } from './query_bar';
import { RemoteProvider } from './remote';
import { RenderableProvider } from './renderable';
Expand Down Expand Up @@ -91,4 +92,5 @@ export const services = {
savedQueryManagementComponent: SavedQueryManagementComponentProvider,
elasticChart: ElasticChartProvider,
supertest: KibanaSupertestProvider,
managementMenu: ManagementMenuProvider,
};
20 changes: 20 additions & 0 deletions test/functional/services/management/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export { ManagementMenuProvider } from './management_menu';
51 changes: 51 additions & 0 deletions test/functional/services/management/management_menu.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { FtrProviderContext } from 'test/functional/ftr_provider_context';

export function ManagementMenuProvider({ getService }: FtrProviderContext) {
const find = getService('find');

class ManagementMenu {
public async getSections() {
const sectionsElements = await find.allByCssSelector(
'.mgtSideBarNav > .euiSideNav__content > .euiSideNavItem'
);

const sections = [];

for (const el of sectionsElements) {
const sectionId = await (await el.findByClassName('euiSideNavItemButton')).getAttribute(
'data-test-subj'
);
const sectionLinks = await Promise.all(
(await el.findAllByCssSelector('.euiSideNavItem > a.euiSideNavItemButton')).map((item) =>
item.getAttribute('data-test-subj')
)
);

sections.push({ sectionId, sectionLinks });
}

return sections;
}
}

return new ManagementMenu();
}
2 changes: 1 addition & 1 deletion x-pack/legacy/plugins/xpack_main/server/xpack_main.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import KbnServer from 'src/legacy/server/kbn_server';
import { Feature, FeatureConfig } from '../../../../plugins/features/server';
import { KibanaFeature } from '../../../../plugins/features/server';
import { XPackInfo, XPackInfoOptions } from './lib/xpack_info';
export { XPackFeature } from './lib/xpack_info';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ describe('ensureAuthorized', () => {
await actionsAuthorization.ensureAuthorized('create', 'myType');

expect(authorization.actions.savedObject.get).toHaveBeenCalledWith('action', 'create');
expect(checkPrivileges).toHaveBeenCalledWith(mockAuthorizationAction('action', 'create'));
expect(checkPrivileges).toHaveBeenCalledWith({
kibana: mockAuthorizationAction('action', 'create'),
});

expect(auditLogger.actionsAuthorizationSuccess).toHaveBeenCalledTimes(1);
expect(auditLogger.actionsAuthorizationFailure).not.toHaveBeenCalled();
Expand Down Expand Up @@ -131,10 +133,12 @@ describe('ensureAuthorized', () => {
ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE,
'create'
);
expect(checkPrivileges).toHaveBeenCalledWith([
mockAuthorizationAction(ACTION_SAVED_OBJECT_TYPE, 'get'),
mockAuthorizationAction(ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, 'create'),
]);
expect(checkPrivileges).toHaveBeenCalledWith({
kibana: [
mockAuthorizationAction(ACTION_SAVED_OBJECT_TYPE, 'get'),
mockAuthorizationAction(ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, 'create'),
],
});

expect(auditLogger.actionsAuthorizationSuccess).toHaveBeenCalledTimes(1);
expect(auditLogger.actionsAuthorizationFailure).not.toHaveBeenCalled();
Expand Down
Loading