elastic / kibana

Your window into the Elastic Stack
https://www.elastic.co/products/kibana
Other
19.69k stars 8.24k forks source link

Unable to share saved objects without `Saved Objects Management` -> `All` privilege #172564

Open legrego opened 11 months ago

legrego commented 11 months ago

Kibana version: >= 8.0 <= 8.13

Describe the bug: Our UI controls which enable sharing saved objects to different spaces has an incorrect authorization check, which prevents some authorized users from selecting spaces to share into. It is incorrectly requiring users to have the Saved Objects Management -> All privilege.

Steps to reproduce:

  1. Run Kibana from https://github.com/elastic/kibana/pull/170359 locally.
  2. Setup at least one custom space, and create dashboards in one of the two spaces.
  3. Create a user with All access to Dashboards in both spaces.
  4. Login as the user created in Step 3, and enter the space which contains the dashboards created in Step 2.
  5. Attempt to share the dashboards into the other space.

Instead of the share completing successfully, the user is presented with a message stating they aren't authorized (see screenshot below)   Expected behavior: You should be allowed to share the dashboards, and the share should complete successfully.

Screenshots (if relevant): image

Any additional context:

The SelectableSpacesControl has an affordance which disables individual spaces for which the user isn't authorized to share saved objects into. The disabled space has a tooltip with a message stating: You need additional privileges to select this space. https://github.com/elastic/kibana/blob/830e8b81509a04bba47f435fe1f51ce385fe6adf/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/selectable_spaces_control.tsx#L59-L67

This component gets its data from the /api/spaces/space endpoint, using the purpose and include_authorized_purposes query parameters:

API Docs: https://www.elastic.co/guide/en/kibana/current/spaces-api-get-all.html#spaces-api-get-all-query-params

https://github.com/elastic/kibana/blob/830e8b81509a04bba47f435fe1f51ce385fe6adf/x-pack/plugins/spaces/server/routes/api/external/get_all.ts#L18-L38

The failing authorization check resides within the SecureSpacesClientWrapper, which contains a mapping of purpose to an underlying privilege check: https://github.com/elastic/kibana/blob/830e8b81509a04bba47f435fe1f51ce385fe6adf/x-pack/plugins/security/server/spaces/secure_spaces_client_wrapper.ts#L26-L40

In the PURPOSE_PRIVILEGE_MAP, you'll notice that the shareSavedObjectsIntoSpace purpose is checking for the authorization.actions.ui.get('savedObjectsManagement', 'shareIntoSpace') privilege action.

This action is a UI capability granted to users with the Saved Objects Management All privilege. This authorization check is too restrictive, and prevents authorized users from sharing saved objects into the target space.

A user should be able to share a saved object of type T into Space S if they have the share_to_space Saved Object Action granted for type T within Space S:

https://github.com/elastic/kibana/blob/830e8b81509a04bba47f435fe1f51ce385fe6adf/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/saved_object.ts#L28


Technical tl;dr:

The secure spaces client wrapper needs a more sophisticated authorization check, which takes into account the types of saved objects that we are interested in, and uses the Saved Objects Actions to perform the authorization check instead of the Saved Objects Management UI Capability check that exists today:

https://github.com/elastic/kibana/blob/830e8b81509a04bba47f435fe1f51ce385fe6adf/x-pack/plugins/security/server/spaces/secure_spaces_client_wrapper.ts#L37-L39

This is not a proposed solution, but illustrates roughly the type of change that may need to happen

diff --git a/x-pack/plugins/security/server/spaces/secure_spaces_client_wrapper.ts b/x-pack/plugins/security/server/spaces/secure_spaces_client_wrapper.ts
index 1e9e25b6b80..877384b16cf 100644
--- a/x-pack/plugins/security/server/spaces/secure_spaces_client_wrapper.ts
+++ b/x-pack/plugins/security/server/spaces/secure_spaces_client_wrapper.ts
@@ -34,9 +34,8 @@ const PURPOSE_PRIVILEGE_MAP: Record<
   findSavedObjects: (authorization) => {
     return [authorization.actions.login, authorization.actions.savedObject.get('config', 'find')];
   },
-  shareSavedObjectsIntoSpace: (authorization) => [
-    authorization.actions.ui.get('savedObjectsManagement', 'shareIntoSpace'),
-  ],
+  shareSavedObjectsIntoSpace: (authorization, types) =>
+    types.map((type) => authorization.actions.savedObject.get(type, 'share_to_space')),
 };

 /** @internal */

Additionally, the UI will need a way to tell the server which saved object types we're interested in sharing. The brute-force method would be to add additional parameters to the /api/spaces/space endpoint, but it might make sense to rethink the approach and introduce a new endpoint. I'll leave that for @elastic/kibana-security to decide.

legrego commented 10 months ago

We are deprioritizing this work due to a change in plans for sharable dashboards.