Skip to content

Commit

Permalink
GAP: Security disables UI capabilities (#25809)
Browse files Browse the repository at this point in the history
* Restructure user profile for granular app privs (#23750)

merging to feature branch for further development

* Fixing saved object capability checking

* Beginning to restructure actions to be used for all action building

* Using actions to build ui capabilities

* dropping /read from client-side userprovide ui capabilities

* Adding some actions

* Using different syntax which will hopefully help with allowing apps to
specify the privileges themselves

* Exposing all saved object operations in the capabilities

* Using actions in security's onPostAuth

* Only loading the default index pattern when it's required

* Only using the navlinks for the "ui capabilities"

* Redirecting from the discover application if the user can't access
kibana:discover

* Redirecting from dashboard if they're hidden

* Features register their privileges now

* Introducing a FeaturesPrivilegesBuilder

* REmoving app from the feature definition

* Adding navlink specific ations

* Beginning to break out the serializer

* Exposing privileges from the authorization service

* Restructuring the privilege/resource serialization to support features

* Adding actions unit tests

* Adding features privileges builders tests

* Adding PrivilegeSerializer tests

* Renaming missed usages

* Adding tests for the privileges serializer

* Adding privileges tests

* Adding registerPrivilegesWithCluster tests

* Better tests

* Restructure user profile for granular app privs (#23750)

merging to feature branch for further development

* Fixing authorization service tests

* Adding ResourceSerializer tests

* Fixing Privileges tests

* Some PUT role tests

* Fixing read ui/api actions

* Introducing uiCapabilities, removing config providers & user profile (#25387)

## Summary
Introduces the concept of "UI Capabilities", which allows Kibana applications to declare capabilities via the `uiCapabilities` injected var, and then use them client-side via the `ui/capabilities` module to inform their rendering decisions.

* Exposing features from xpackMainPlugin

* Adding navlink:* to the "reserved privileges"

* navlink -> navLink | nav_linknavlink -> navLink | nav_linknavlink ->
navLink | nav_linknavlink -> navLink | nav_linknavlink -> navLink |
nav_linknavlink -> navLink | nav_linknavlink -> navLink |
nav_linknavlink -> navLink | nav_linknavlink -> navLink | nav_link

* Automatically determining navlink based ui capabilities

* Backing out changes that got left behind

* Using ui actions for navlinks

* Adding TODOs

* Ui -> UI

* Deleting unused file

* Removing api: [] as it's not necessary anymore

* Fixing graph saved object privileges

* Privileges are now async

* Pushing the asycnchronicity to the privileges "service"

* Adding TODO

* Providing initial value for reduce

* adds uiCapabilities to test_entry_template

* Adding config to APM/ML feature privileges

* Commenting out obviously failing test so we can get CI greeenn

* Fixing browser tests

* First, very crappy implementation

* Adding tests for disabling ui capabilities

* All being set to false no longer requires a clone

* Using _.mapValues makes this a lot more readable

* Checking those privileges dynamically

* Fixing some broken stuff when i introduced checkPrivilegesDynamically

* Adding conditional plugin tests

* Renaming conditional plugin to optional plugin

* Fixing type errors

* GAP - Actions Restructured and Extensible (#25347)

* Restructure user profile for granular app privs (#23750)

merging to feature branch for further development

* Fixing saved object capability checking

* Beginning to restructure actions to be used for all action building

* Using actions to build ui capabilities

* dropping /read from client-side userprovide ui capabilities

* Adding some actions

* Using different syntax which will hopefully help with allowing apps to
specify the privileges themselves

* Exposing all saved object operations in the capabilities

* Using actions in security's onPostAuth

* Only loading the default index pattern when it's required

* Only using the navlinks for the "ui capabilities"

* Redirecting from the discover application if the user can't access
kibana:discover

* Redirecting from dashboard if they're hidden

* Features register their privileges now

* Introducing a FeaturesPrivilegesBuilder

* REmoving app from the feature definition

* Adding navlink specific ations

* Beginning to break out the serializer

* Exposing privileges from the authorization service

* Restructuring the privilege/resource serialization to support features

* Adding actions unit tests

* Adding features privileges builders tests

* Adding PrivilegeSerializer tests

* Renaming missed usages

* Adding tests for the privileges serializer

* Adding privileges tests

* Adding registerPrivilegesWithCluster tests

* Better tests

* Fixing authorization service tests

* Adding ResourceSerializer tests

* Fixing Privileges tests

* Some PUT role tests

* Fixing read ui/api actions

* Exposing features from xpackMainPlugin

* Adding navlink:* to the "reserved privileges"

* navlink -> navLink | nav_linknavlink -> navLink | nav_linknavlink ->
navLink | nav_linknavlink -> navLink | nav_linknavlink -> navLink |
nav_linknavlink -> navLink | nav_linknavlink -> navLink |
nav_linknavlink -> navLink | nav_linknavlink -> navLink | nav_link

* Automatically determining navlink based ui capabilities

* Backing out changes that got left behind

* Using ui actions for navlinks

* Adding TODOs

* Ui -> UI

* Deleting unused file

* Removing api: [] as it's not necessary anymore

* Fixing graph saved object privileges

* Privileges are now async

* Pushing the asycnchronicity to the privileges "service"

* Adding TODO

* Providing initial value for reduce

* adds uiCapabilities to test_entry_template

* Adding config to APM/ML feature privileges

* Commenting out obviously failing test so we can get CI greeenn

* Fixing browser tests

* Goodbyyeee

* Adding app actions to the reserved privileges

* Restructure user profile for granular app privs (#23750)

merging to feature branch for further development

* Introducing uiCapabilities, removing config providers & user profile (#25387)

## Summary
Introduces the concept of "UI Capabilities", which allows Kibana applications to declare capabilities via the `uiCapabilities` injected var, and then use them client-side via the `ui/capabilities` module to inform their rendering decisions.

* GAP - Actions Restructured and Extensible (#25347)

* Restructure user profile for granular app privs (#23750)

merging to feature branch for further development

* Fixing saved object capability checking

* Beginning to restructure actions to be used for all action building

* Using actions to build ui capabilities

* dropping /read from client-side userprovide ui capabilities

* Adding some actions

* Using different syntax which will hopefully help with allowing apps to
specify the privileges themselves

* Exposing all saved object operations in the capabilities

* Using actions in security's onPostAuth

* Only loading the default index pattern when it's required

* Only using the navlinks for the "ui capabilities"

* Redirecting from the discover application if the user can't access
kibana:discover

* Redirecting from dashboard if they're hidden

* Features register their privileges now

* Introducing a FeaturesPrivilegesBuilder

* REmoving app from the feature definition

* Adding navlink specific ations

* Beginning to break out the serializer

* Exposing privileges from the authorization service

* Restructuring the privilege/resource serialization to support features

* Adding actions unit tests

* Adding features privileges builders tests

* Adding PrivilegeSerializer tests

* Renaming missed usages

* Adding tests for the privileges serializer

* Adding privileges tests

* Adding registerPrivilegesWithCluster tests

* Better tests

* Fixing authorization service tests

* Adding ResourceSerializer tests

* Fixing Privileges tests

* Some PUT role tests

* Fixing read ui/api actions

* Exposing features from xpackMainPlugin

* Adding navlink:* to the "reserved privileges"

* navlink -> navLink | nav_linknavlink -> navLink | nav_linknavlink ->
navLink | nav_linknavlink -> navLink | nav_linknavlink -> navLink |
nav_linknavlink -> navLink | nav_linknavlink -> navLink |
nav_linknavlink -> navLink | nav_linknavlink -> navLink | nav_link

* Automatically determining navlink based ui capabilities

* Backing out changes that got left behind

* Using ui actions for navlinks

* Adding TODOs

* Ui -> UI

* Deleting unused file

* Removing api: [] as it's not necessary anymore

* Fixing graph saved object privileges

* Privileges are now async

* Pushing the asycnchronicity to the privileges "service"

* Adding TODO

* Providing initial value for reduce

* adds uiCapabilities to test_entry_template

* Adding config to APM/ML feature privileges

* Commenting out obviously failing test so we can get CI greeenn

* Fixing browser tests

* Goodbyyeee

* Adding app actions to the reserved privileges

* Update x-pack/plugins/security/server/lib/authorization/disable_ui_capabilities.ts

Co-Authored-By: kobelb <[email protected]>

* Update x-pack/plugins/security/server/lib/authorization/check_privileges_dynamically.ts

Co-Authored-By: kobelb <[email protected]>

* Disabling all ui capabilities if route is anonymous

* More typescript

* Even more typescript

* Updating snapshot

* Less any

* More safer

* Another one

* Restructure user profile for granular app privs (#23750)

merging to feature branch for further development

* Introducing uiCapabilities, removing config providers & user profile (#25387)

## Summary
Introduces the concept of "UI Capabilities", which allows Kibana applications to declare capabilities via the `uiCapabilities` injected var, and then use them client-side via the `ui/capabilities` module to inform their rendering decisions.

* GAP - Actions Restructured and Extensible (#25347)

* Restructure user profile for granular app privs (#23750)

merging to feature branch for further development

* Fixing saved object capability checking

* Beginning to restructure actions to be used for all action building

* Using actions to build ui capabilities

* dropping /read from client-side userprovide ui capabilities

* Adding some actions

* Using different syntax which will hopefully help with allowing apps to
specify the privileges themselves

* Exposing all saved object operations in the capabilities

* Using actions in security's onPostAuth

* Only loading the default index pattern when it's required

* Only using the navlinks for the "ui capabilities"

* Redirecting from the discover application if the user can't access
kibana:discover

* Redirecting from dashboard if they're hidden

* Features register their privileges now

* Introducing a FeaturesPrivilegesBuilder

* REmoving app from the feature definition

* Adding navlink specific ations

* Beginning to break out the serializer

* Exposing privileges from the authorization service

* Restructuring the privilege/resource serialization to support features

* Adding actions unit tests

* Adding features privileges builders tests

* Adding PrivilegeSerializer tests

* Renaming missed usages

* Adding tests for the privileges serializer

* Adding privileges tests

* Adding registerPrivilegesWithCluster tests

* Better tests

* Fixing authorization service tests

* Adding ResourceSerializer tests

* Fixing Privileges tests

* Some PUT role tests

* Fixing read ui/api actions

* Exposing features from xpackMainPlugin

* Adding navlink:* to the "reserved privileges"

* navlink -> navLink | nav_linknavlink -> navLink | nav_linknavlink ->
navLink | nav_linknavlink -> navLink | nav_linknavlink -> navLink |
nav_linknavlink -> navLink | nav_linknavlink -> navLink |
nav_linknavlink -> navLink | nav_linknavlink -> navLink | nav_link

* Automatically determining navlink based ui capabilities

* Backing out changes that got left behind

* Using ui actions for navlinks

* Adding TODOs

* Ui -> UI

* Deleting unused file

* Removing api: [] as it's not necessary anymore

* Fixing graph saved object privileges

* Privileges are now async

* Pushing the asycnchronicity to the privileges "service"

* Adding TODO

* Providing initial value for reduce

* adds uiCapabilities to test_entry_template

* Adding config to APM/ML feature privileges

* Commenting out obviously failing test so we can get CI greeenn

* Fixing browser tests

* Goodbyyeee

* Adding app actions to the reserved privileges

* update snapshot

* Update x-pack/plugins/security/server/lib/authorization/check_privileges.ts

Co-Authored-By: kobelb <[email protected]>

* Update x-pack/plugins/security/server/lib/authorization/check_privileges.ts

Co-Authored-By: kobelb <[email protected]>

* Fixing type errors

* Only disabling navLinks if a feature is registered for them

* Adding non i18n'ed tooltip

* Making metadata and tooltip optional

* i18n'ing tooltips

* Responding to peer review comments
  • Loading branch information
kobelb authored Dec 3, 2018
1 parent e032111 commit fd14b08
Show file tree
Hide file tree
Showing 30 changed files with 2,408 additions and 2,417 deletions.
6 changes: 6 additions & 0 deletions x-pack/plugins/ml/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import { resolve } from 'path';
import Boom from 'boom';
import { i18n } from '@kbn/i18n';
import { checkLicense } from './server/lib/check_license';
import { mirrorPluginStatus } from '../../server/lib/mirror_plugin_status';
import { jobRoutes } from './server/routes/anomaly_detectors';
Expand Down Expand Up @@ -70,6 +71,11 @@ export const ml = (kibana) => {
navLinkId: 'ml',
privileges: {
all: {
metadata: {
tooltip: i18n.translate('xpack.ml.privileges.tooltip', {
defaultMessage: 'The machine_learning_user or machine_learning_admin role should be assigned to grant access'
})
},
app: ['ml'],
savedObject: {
all: [],
Expand Down
6 changes: 6 additions & 0 deletions x-pack/plugins/monitoring/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { i18n } from '@kbn/i18n';
import { LOGGING_TAG, KIBANA_MONITORING_LOGGING_TAG } from './common/constants';
import { requireUIRoutes } from './server/routes';
import { instantiateClient } from './server/es_client/instantiate_client';
Expand Down Expand Up @@ -61,6 +62,11 @@ export const init = (monitoringPlugin, server) => {
navLinkId: 'monitoring',
privileges: {
all: {
metadata: {
tooltip: i18n.translate('xpack.monitoring.privileges.tooltip', {
defaultMessage: 'The monitoring_user role should be assigned to grant access'
})
},
app: ['monitoring'],
savedObject: {
all: [],
Expand Down
36 changes: 25 additions & 11 deletions x-pack/plugins/security/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ import { checkLicense } from './server/lib/check_license';
import { initAuthenticator } from './server/lib/authentication/authenticator';
import { SecurityAuditLogger } from './server/lib/audit_logger';
import { AuditLogger } from '../../server/lib/audit_logger';
import { createAuthorizationService, registerPrivilegesWithCluster } from './server/lib/authorization';
import { createAuthorizationService, disableUICapabilitesFactory, registerPrivilegesWithCluster } from './server/lib/authorization';
import { watchStatusAndLicenseToInitialize } from '../../server/lib/watch_status_and_license_to_initialize';
import { SecureSavedObjectsClientWrapper } from './server/lib/saved_objects_client/secure_saved_objects_client_wrapper';
import { deepFreeze } from './server/lib/deep_freeze';
import { createOptionalPlugin } from './server/lib/optional_plugin';

export const security = (kibana) => new kibana.Plugin({
id: 'security',
Expand Down Expand Up @@ -88,6 +89,21 @@ export const security = (kibana) => new kibana.Plugin({
sessionTimeout: config.get('xpack.security.sessionTimeout'),
enableSpaceAwarePrivileges: config.get('xpack.spaces.enabled'),
};
},
replaceInjectedVars: async function (originalInjectedVars, request, server) {
const disableUICapabilites = disableUICapabilitesFactory(server, request);
// if we're an anonymous route, we disable all ui capabilities
if (request.route.settings.auth === false) {
return {
...originalInjectedVars,
uiCapabilities: disableUICapabilites.all(originalInjectedVars.uiCapabilities)
};
}

return {
...originalInjectedVars,
uiCapabilities: await disableUICapabilites.usingPrivileges(originalInjectedVars.uiCapabilities)
};
}
},

Expand Down Expand Up @@ -117,8 +133,10 @@ export const security = (kibana) => new kibana.Plugin({

const { savedObjects } = server;

const spaces = createOptionalPlugin(config, 'xpack.spaces', server.plugins, 'spaces');

// exposes server.plugins.security.authorization
const authorization = createAuthorizationService(server, xpackInfoFeature, savedObjects.types, xpackMainPlugin);
const authorization = createAuthorizationService(server, xpackInfoFeature, savedObjects.types, xpackMainPlugin, spaces);
server.expose('authorization', deepFreeze(authorization));

watchStatusAndLicenseToInitialize(xpackMainPlugin, plugin, async (license) => {
Expand Down Expand Up @@ -147,17 +165,15 @@ export const security = (kibana) => new kibana.Plugin({

savedObjects.addScopedSavedObjectsClientWrapperFactory(Number.MIN_VALUE, ({ client, request }) => {
if (authorization.mode.useRbacForRequest(request)) {
const { spaces } = server.plugins;

return new SecureSavedObjectsClientWrapper({
actions: authorization.actions,
auditLogger,
baseClient: client,
checkPrivilegesWithRequest: authorization.checkPrivilegesWithRequest,
checkPrivilegesDynamicallyWithRequest: authorization.checkPrivilegesDynamicallyWithRequest,
errors: savedObjects.SavedObjectsClient.errors,
request,
savedObjectTypes: savedObjects.types,
spaces,
});
}

Expand Down Expand Up @@ -193,16 +209,15 @@ export const security = (kibana) => new kibana.Plugin({
server.ext('onPostAuth', async function (req, h) {
const path = req.path;

const { actions, checkPrivilegesWithRequest } = server.plugins.security.authorization;
const checkPrivileges = checkPrivilegesWithRequest(req);
const { actions, checkPrivilegesDynamicallyWithRequest } = server.plugins.security.authorization;
const checkPrivileges = checkPrivilegesDynamicallyWithRequest(req);

// Enforce app restrictions
if (path.startsWith('/app/')) {
const appId = path.split('/', 3)[2];
const appAction = actions.app.get(appId);

// TODO: Check this at the specific space
const checkPrivilegesResponse = await checkPrivileges.globally(appAction);
const checkPrivilegesResponse = await checkPrivileges(appAction);
if (!checkPrivilegesResponse.hasAllRequested) {
return Boom.notFound();
}
Expand All @@ -218,8 +233,7 @@ export const security = (kibana) => new kibana.Plugin({
const feature = path.split('/', 3)[2];
const apiActions = actionTags.map(tag => actions.api.get(`${feature}/${tag.split(':', 2)[1]}`));

// TODO: Check this at the specific space
const checkPrivilegesResponse = await checkPrivileges.globally(apiActions);
const checkPrivilegesResponse = await checkPrivileges(apiActions);
if (!checkPrivilegesResponse.hasAllRequested) {
return Boom.notFound();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`throws error when invoked before it's available 1`] = `"Plugin accessed before it's available"`;

exports[`throws error when invoked before it's available 2`] = `"Plugin accessed before it's available"`;

exports[`throws error when invoked before it's available 3`] = `"Plugin accessed before it's available"`;

exports[`throws error when invoked when it's not enabled 1`] = `"Plugin isn't enabled, check isEnabled before using"`;

exports[`throws error when invoked when it's not enabled 2`] = `"Plugin isn't enabled, check isEnabled before using"`;

exports[`throws error when invoked when it's not enabled 3`] = `"Plugin isn't enabled, check isEnabled before using"`;

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`#atSpace throws error when checking for login and user has login but doesn't have version 1`] = `[Error: Multiple versions of Kibana are running against the same Elasticsearch cluster, unable to authorize user.]`;

exports[`#atSpace with a malformed Elasticsearch response throws a validation error when an extra privilege is present in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because ["saved_object:bar-type/get" is not allowed]]]]`;

exports[`#atSpace with a malformed Elasticsearch response throws a validation error when privileges are missing in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because [child "saved_object:foo-type/get" fails because ["saved_object:foo-type/get" is required]]]]]`;

exports[`#atSpaces throws error when Elasticsearch returns malformed response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because [child "mock-action:version" fails because ["mock-action:version" is required]]]]]`;

exports[`#atSpaces throws error when checking for login and user has login but doesn't have version 1`] = `[Error: Multiple versions of Kibana are running against the same Elasticsearch cluster, unable to authorize user.]`;

exports[`#atSpaces with a malformed Elasticsearch response throws a validation error when an a space is missing in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_2" fails because ["space:space_2" is required]]]]`;

exports[`#atSpaces with a malformed Elasticsearch response throws a validation error when an extra privilege is present in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_2" fails because ["space:space_2" is required]]]]`;

exports[`#atSpaces with a malformed Elasticsearch response throws a validation error when an extra space is present in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because ["space:space_3" is not allowed]]]`;

exports[`#atSpaces with a malformed Elasticsearch response throws a validation error when privileges are missing in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_2" fails because ["space:space_2" is required]]]]`;

exports[`#globally throws error when Elasticsearch returns malformed response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because [child "mock-action:version" fails because ["mock-action:version" is required]]]]]`;

exports[`#globally throws error when checking for login and user has login but doesn't have version 1`] = `[Error: Multiple versions of Kibana are running against the same Elasticsearch cluster, unable to authorize user.]`;

exports[`#globally with a malformed Elasticsearch response throws a validation error when an extra privilege is present in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because ["saved_object:bar-type/get" is not allowed]]]]`;

exports[`#globally with a malformed Elasticsearch response throws a validation error when privileges are missing in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because [child "saved_object:foo-type/get" fails because ["saved_object:foo-type/get" is required]]]]]`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`usingPrivileges checkPrivileges errors otherwise it throws the error 1`] = `"something else entirely"`;
Loading

0 comments on commit fd14b08

Please sign in to comment.