Role-based access control

edit

Role-based access control (RBAC) in Kibana relies upon the application privileges that Elasticsearch exposes. This allows Kibana to define the privileges that Kibana wishes to grant to users, assign them to the relevant users using roles, and then authorize the user to perform a specific action. This is handled within a secured instance of the SavedObjectsClient and available transparently to consumers when using request.getSavedObjectsClient() or savedObjects.getScopedSavedObjectsClient().

Kibana Privileges

edit

When Kibana first starts up, it executes the following POST request against Elasticsearch. This synchronizes the definition of the privileges with various actions which are later used to authorize a user:

POST /_xpack/security/privilege
Content-Type: application/json
Authorization: Basic kibana changeme

{
   "kibana-.kibana":{
       "all":{
           "application":"kibana-.kibana",
           "name":"all",
           "actions":[
               "version:7.0.0-alpha1-SNAPSHOT",
               "action:login",
               "action:*"
           ],
           "metadata":{}
       },
       "read":{
           "application":"kibana-.kibana",
           "name":"read",
           "actions":[
               "version:7.0.0-alpha1-SNAPSHOT",
               "action:login",
               "action:saved_objects/dashboard/get",
               "action:saved_objects/dashboard/bulk_get",
               "action:saved_objects/dashboard/find",
               ...
           ],"metadata":{}}
   }
}

The application is created by concatenating the prefix of kibana- with the value of kibana.index from the kibana.yml, so different Kibana tenants are isolated from one another.

Assigning Kibana Privileges

edit

Kibana privileges are assigned to specific roles using the applications element. For example, the following role assigns the all privilege at * resources (which will in the future be used to secure spaces) to the default Kibana application:

"new_kibana_user": {
   "applications": [
     {
       "application": "kibana-.kibana",
       "privileges": [
         "all"
       ],
       "resources": [
         "*"
       ]
     }
   ]
 }

Roles that grant Kibana privileges should be managed using the Kibana Role Management API or the Management / Security / Roles page, not directly using the Elasticsearch role management API. This role can then be assigned to users using the Elasticsearch user management APIs.

Authorization

edit

The Elasticsearch has privileges API determines whether the user is authorized to perform a specific action:

POST /_xpack/security/user/_has_privileges
Content-Type: application/json
Authorization: Basic foo_read_only_user password

{
   "applications":[
       {
           "application":"kibana-.kibana",
           "resources":["*"],
           "privileges":[
             "action:saved_objects/dashboard/save",
           ]
       }
   ]
}

Elasticsearch checks if the user is granted a specific action. If the user is assigned a role that grants a privilege, Elasticsearch uses the Kibana privileges definition to associate this with the actions, which makes authorizing users more intuitive and flexible programatically.

Once we have authorized the user to perform a specific action, we can execute the request using callWithInternalUser.

Legacy Fallback

edit

Users have existing roles that rely on index privileges to the .kibana index. The legacy fallback uses the callWithRequest method when the user doesn’t have any application privileges. This relies on the user having index privileges on .kibana. The legacy fallback will be available until 7.0.

Within the secured instance of the SavedObjectsClient the _has_privileges check determines if the user has any index privileges on the .kibana index:

POST /_xpack/security/user/_has_privileges
Content-Type: application/json
Authorization: Basic foo_legacy_user password

{
   "applications":[
       {
           "application":"kibana-.kibana",
           "resources":["*"],
           "privileges":[
             "action:saved_objects/dashboard/save"
           ]
       }
   ],
   "index": [
       {
           "names": ".kibana",
           "privileges": ["create", "delete", "read", "view_index_metadata"]
       }
   ]
}

Here is an example response if the user does not have application privileges, but does have privileges on the .kibana index:

{
  "username": "foo_legacy_user",
  "has_all_requested": false,
  "cluster": {},
  "index": {
    ".kibana": {
      "read": true,
      "view_index_metadata": true,
      "create": true,
      "delete": true
    }
  },
  "application": {
    "kibana-.kibana": {
      "*": {
        "action:saved_objects/dashboard/save": false
      }
    }
  }
}

Kibana automatically detects that the request could be executed against .kibana using callWithRequest and does so.

When the user first logs into Kibana, if they have no application privileges and will have to rely on the legacy fallback, Kibana logs a deprecation warning similar to the following:

${username} relies on index privileges on the {kib} index. This is deprecated and will be removed in {kib} 7.0

Reserved roles

edit

Ideally, the kibana_user and kibana_dashboard_only_user roles should only use application privileges, and no longer have index privileges on the .kibana index. However, making this switch forces the user to incur downtime if Elasticsearch is upgraded to >= 6.4, and Kibana is running < 6.4. To mitigate this downtime, for the 6.x releases the kibana_user and kibana_dashbord_only_user roles have both application privileges and index privileges. When Kibana is running >= 6.4 it uses the application privileges to authorize the user, but when Kibana is running < 6.4 Kibana relies on the direct index privileges.