Kibana Multi-Tenancy
Content
Important note for SearchGuard in versions 2.x.x
Any data created before implementing the
multi-tenancy
module may be lost, necessitating a secure backup.
If you’re upgrading to SG FLX 2.0.0, please review the upgrade guide. This version introduces backwards-incompatible changes.
Tenants: Definition
A Kibana tenant is a named container for storing saved objects. A tenant can be assigned to one or more Search Guard roles. The role can have read-write or read-only access to the tenant and thus the saved objects in it. A Kibana user selects the tenant that he or she wants to work with. Search Guard ensures that the saved objects are placed in the selected tenant.
The Global tenant serves as a shared platform for all users, acting as the default
when no specific tenant is designated. It’s crucial to
grant users access to the global tenant. Write access to Global tenant can be achieved by assigning
role SGS_KIBANA_USER
.
The Private tenant is not shared. It is only accessible for the currently logged-in user.
Elasticsearch: Configuration
Multi-Tenancy configuration
Multi-Tenancy is configured in sg_frontend_multi_tenancy.yml
.
The following configuration keys are available:
For FLX v2.0.0 and higher
Name | Description |
---|---|
server_user | String, the name of the Kibana server user as configured in your kibana.yml. The names must match in both configurations. Default: kibanaserver . |
index | String, the name of the Kibana index as configured in your kibana.yml. The index name must match in both configurations. Default: .kibana . |
global_tenant_enabled | boolean, enable or disable the SGS_GLOBAL_TENANT. Default: true. |
preferred_tenants | List, a list of tenants to try to use if the user has not requested a tenant yet. Default empty. |
Enabling / Disabling MT
Please keep in mind that due to some technical limitations once you enable MT, it cannot be easily disabled. In such case please contact the support team.
- Run the following command:
./sgctl.sh special enable-mt
- Header
sgtenant
needs to be forwarded to Elasticsearch, which can be achieved by adding the header name to the propertyelasticsearch.requestHeadersWhitelist
in thekibana.yml
file. - Check roles assigned to users. Users with the role
SGS_KIBANA_USER_NO_MT
are not able to access the Kibana user interface when multitenacy is enabled. Therefore, an administrator should consider assigning to users the following build-in roles:SGS_KIBANA_USER
SGS_KIBANA_USER_NO_GLOBAL_TENANT
It is also possible to use custom roles. However, it is important to ensure each user has access to at least one tenant. Otherwise, the user is unable to log into Kibana.
For versions prior to FLX v2.0.0
Name | Description |
---|---|
enabled | boolean, enable or disable Multi-Tenancy. Default: true. |
server_user | String, the name of the Kibana server user as configured in your kibana.yml. The names must match in both configurations. Default: kibanaserver . |
index | String, the name of the Kibana index as configured in your kibana.yml. The index name must match in both configurations. Default: .kibana . |
Defining tenants
For FLX v2.0.0 and higher
If you do not configure anything special, every user has access to the Global tenant by default, with read/write access.
Private tenants are no longer supported.
You can define an arbitrary number of additional tenants in sg_tenants.yml
, for example:
admin_tenant:
description: "The admin tenant"
human_resources:
description: "The human resources tenant"
For versions prior to FLX v2.0.0
If you do not configure anything special, every user has access to the Global and Private tenant by default, with read/write access.
You can define an arbitrary number of additional tenants in sg_tenants.yml
, for example:
admin_tenant:
description: "The admin tenant"
human_resources:
description: "The human resources tenant"
Assigning tenants to Search Guard roles
You can assign one or more tenants to Search Guard roles in sg_roles.yml
, for example:
sg_human_resources:
cluster_permissions:
- ...
index_permissions:
- ...
tenant_permissions:
- tenant_patterns:
- human_resources
allowed_actions:
- SGS_KIBANA_ALL_WRITE
- tenant_patterns:
- admin_tenant
allowed_actions:
- SGS_KIBANA_ALL_READ
In this example, a user that has the role sg_human_resources
has access to the tenant human_resources with read/write access, and read-only access to the tenant admin_tenant
.
At the moment the only allowed values for allowed_actions
are SGS_KIBANA_ALL_WRITE
and SGS_KIBANA_ALL_READ
. The option to assign finer-grained permissions will follow soon.
Widcards and regular expressions in tenant patterns
You can use wildcards and regular expression in tenant names to make them more dynamic.
- An asterisk (
*
) will match any character sequence (or an empty sequence)*my*index
will matchmy_first_index
as well asmyindex
but notmyindex1
.
- A question mark (
?
) will match any single character (but NOT empty character)?kibana
will match.kibana
but notkibana
- Regular expressions have to be enclosed in
/
:'/<java regex>/'
'/\S*/'
will match any non whitespace characters
Example:
sg_own_index:
cluster_permissions:
- ...
index_permissions:
- ...
tenant_permissions:
- tenant_patterns:
- 'dept_*'
- '/logstash-[1-9]{2}/'
allowed_actions:
- "SGS_KIBANA_ALL_WRITE"
User attributes in tenant patterns
You can use user attributes when defining tenant patterns to make them more dynamic.
For example, if the user has an attribute department
, you can define a tenant pattern like:
sg_own_index:
cluster_permissions:
- ...
index_permissions:
- ...
tenant_permissions:
- tenant_patterns:
- 'dept_${user.attrs.department}'
allowed_actions:
- "SGS_KIBANA_ALL_WRITE"
Setting preferred / default tenants
For FLX v2.0.0 and higher
In order to choose user’s preferred / default tenant Search Guard will:
- return first tenant to which user has write access or user has read access and tenant exists
- Search Guard checks tenants in the following order:
- list of preferred tenants
- Global tenant
- tenants available to the user
- Global tenant is not taken into account if it’s disabled
For versions prior to FLX v2.0.0
In older versions, configuration and selection of the preferred / default tenant is done on the Kibana plugin side as described below.
Kibana: Plugin Configuration
Kibana requires you to whitelist all HTTP headers that should be passed from Kibana to Elasticsearch. The Multi-Tenancy feature uses one specific header, named sgtenant
. Add this header and also the standard Authorization
header to the white list. If the sgtenant
header is not whitelisted, an error message is logged on startup and the status of Kibana will be red.
elasticsearch.requestHeadersWhitelist: ["sgtenant", "Authorization", ...]
Also, please check that the Kibana server user and the Kibana index name matches in both kibana.yml and sg_frontend_multi_tenancy.yml. The contents of the following keys must match:
Kibana server user:
kibana.yml: elasticsearch.username
sg_frontend_multi_tenancy.yml: server_user
Kibana index name:
kibana.yml: kibana.index
sg_frontend_multi_tenancy.yml: index
Enable Multi-Tenancy
For FLX v2.0.0 and higher
As of Search Guard FLX v2.0.0, the Multi-Tenancy configuration has been removed from the Kibana plugin. Instead, Multi-Tenancy is configured in the Elasticsearch plugin, as described in the Elasticsearch: Configuration section above.
For versions prior to FLX v2.0.0
Enable the Multi-Tenancy feature in kibana.yml
by adding:
searchguard.multitenancy.enabled: true
Kibana: Tenant Configuration
For FLX v2.0.0 and higher
As of Search Guard FLX v2.0.0, the Multi-Tenancy configuration has been removed from the Kibana plugin. Instead, Multi-Tenancy is configured in the Elasticsearch plugin, as described in the Elasticsearch: Configuration section above.
For versions prior to FLX v2.0.0
By default, Search Guard offers two default tenants for each user, Global and Private. The Global tenant is shared between all users and uses the Kibana index as configured in kibana.yml
. Thus, all dashboards and visualizations that have been created prior to installing Multi-Tenancy can be found in this tenant.
The Private tenant is meant as a user’s private space, thus is not shared.
You can enable and disable these tenants by the following kibana.yml
configuration keys:
Name | Description |
---|---|
searchguard.multitenancy.tenants.enable_global | boolean, enable or disable the global tenant. Default: true. |
searchguard.multitenancy.tenants.enable_private | boolean, enable or disable the private tenant. Default: true. |
Note that each user needs to have at least one tenant configured, otherwise Search Guard does not know which tenant to use. If you disable both the Global and Private tenant, and the user does not have any other tenants configured, login will not be possible.
Kibana: Setting preferred / default tenants
For FLX v2.0.0 and higher
As of Search Guard FLX v2.0.0, the Multi-Tenancy configuration has been removed from the Kibana plugin. Instead, Multi-Tenancy is configured in the Elasticsearch plugin, as described in the Elasticsearch: Configuration section above.
For versions prior to FLX v2.0.0
If a user logs in the first time and has not chosen a tenant yet, Search Guard will
- collect all available tenants for the logged in user
- sort them alphabetically
- if enabled, add the global and private tenant on top
- choose the first tenant from this list
For FLX v2.0.0 and higher
Please see the configuration section for ElasticSearch above.
If you want to change the way Search Guard selects the default tenant, configure the preferred tenants in kibana.yml
:
For versions prior to FLX v2.0.0
searchguard.multitenancy.tenants.preferred: ["tenant1","tenant2",...]
Search Guard will compare the list of preferred tenants with the list of available tenants for the logged in user, and chose the first matching tenant.
Kibana: Selecting tenants by query parameter
Tenants can also be switched by adding a query parameter to the URL. This is especially handy if you want to share a visualization or dashboard.
For any Kibana URL, you can add a query param sgtenant
which will overwrite the currently selected tenant.
http://localhost:5601/app/kibana?sgtenant=mytenant#/visualize/edit/919f5810-55ff-11e7-a198-5f6d82ac1c15?_g=()
Make sure to add the the query parameter before the hash sign.
Using the Kibana API
Kibana offers an API for saved objects like index patterns, dashboards and visualizations. In order to use this API in conjunction with tenants, specify the tenant by adding the sgtenant
HTTP header:
curl \
-u hr_employee:hr_employee \
-H "sgtenant: management" \
-H 'Content-Type: application/json' \
-H "kbn-xsrf: true" \
-XGET "http://localhost:5601/api/saved_objects"
Under the hood
For FLX v2.0.0 and higher
When the Multi-Tenancy is enabled, then all Kibana saved objects which does not belong to the global tenant are modified in the following way on the storiage level.
- The ID of the saved object is extended with the tenant ID.
- Attribute
sg_tenant
, which contains tenant ID, is added to each saved object. Please keep in mind that this is only an implementation detail and can be changed without warning in the future. Therefore, software integrated with Search Guard and Elasticsearch should not rely on this behaviour.
The procedure described above applies only to the following indices
.kibana
.kibana_analytics
.kibana_ingest
.kibana_security_solution
.kibana_alerting_cases.
When an HTTP request with header sgtenant
or sg_tenant
or proper query parameter is sent to Elasticsearch, the Search Guard imposes additional filtering on saved objects. Thus, saved objects that only belong to the tenant specified in the header (or query parameter) are processed. Therefore, when Multi-Tenancy is enabled, the user authorized to use Kibana should not have assigned any permissions related to the above indices. Such index permissions allow users to circumvent checks imposed by the Multi-Tenancy module. An example of the role which grants such permission to users is SGS_KIBANA_USER_NO_MT
. Thus, users should not be assigned the role in environments where Multi-Tenancy is enabled. Furthermore, the Search Guard removes a part of the saved object ID related to Multi-Tenancy before returning responses. On the other hand, the attribute sg_tenant
is not removed from responses.
Search Guard treats the global tenant exceptionally. The tenant’s saved object IDs are not extended, and the attribute sg _tenant
is not added.
For versions prior to FLX v2.0.0: Index rewriting, Snapshot & Restore
In a plain vanilla Kibana installation, all saved objects are stored in one global index. Search Guard maintains separate indices for each tenant.
For example, if your Kibana index is called “.kibana”, and the currently selected tenant is “human_resources”, Search Guard will create a new index called something like “.kibana_1592542611_humanresources”, and places saved objects will in this index.
The structure of the index name for a regular tenant is:
<kibana index name>_<tenant hashcode>_<tenant name>
There are two default tenants in additions, Global and Private. The structure of the index name for the Private tenants is:
<kibana index name>_<username hashcode>_<username>
The structure of the index name for the Global tenants is:
<kibana index name>
Search Guard automatically makes sure that the index names do not contain any illegal characters. Search Guard also checks the user’s permissions for the selected tenant index. You do not need to configure anything special in sg_roles.yml
, apart from the standard permissions for the Kibana index. See Using Search Guard with Kibana for further information.
If you use snapshot / restore, you need to include all tenant indices, otherwise you will loose data!
In order to include all Kibana indices in your backup / snapshot, the easiest way is to simply use wildcards:
<kibana index name>*
Limitations of multi-tenancy implementation in FLX v2.0.0 and higher
Most of the limitations are related to how saved object IDs are modified by SearchGuard to map saved objects to tenants. SearchGuard appends to each saved object’s ID a tenant ID. SearchGuard also replaces an extended version of the saved object ID with the genuine one before returning saved objects via API. The genuine version of the saved object ID is returned only when a tenant is selected via the appropriate HTTP header. However, this is not always possible. The inability to restore genuine saved object IDs results in the following limitations
- Cannot use document ID in query. Such a query may not gain the desired result or gain incorrect results. Example of such a query:
GET /.kibana/_search { "query": { "ids": { "values": [ "space:custom" ] } } }
- Scripts (e.g. painless scripts) may receive document ID in an extended version. An example of such a script is visible below. The below script will set an extended version of ID in the
description
attribute.POST /.kibana/_update/space:myspace { "script": { "source": "ctx._source.space.description = ctx['_id']", "lang": "painless" } }
- Error responses and error messages can contain ID with tenant scope. An example of such a response with extended ID
space:nonspace__sg_ten__-152937574_admintenant
is visible below. The genuine saved object ID isspace:nonspace
.{ "error": { "root_cause": [ { "type": "document_missing_exception", "reason": "[space:nonspace__sg_ten__-152937574_admintenant]: document missing", "index_uuid": "P-DqhmPUQQO8zzSt19nF7g", "shard": "0", "index": ".kibana_8.12.0_001" } ], "type": "document_missing_exception", "reason": "[space:nonspace__sg_ten__-152937574_admintenant]: document missing", "index_uuid": "P-DqhmPUQQO8zzSt19nF7g", "shard": "0", "index": ".kibana_8.12.0_001" }, "status": 404 }
Additionally, limitations not related to ID extensions are
- Saved objects contain an additional attribute
sg_tenant
which contains tenant identification. - An extended version of the document ID may be returned in the query result if the query reads the content of Kibana-related indices and the tenant is not selected via the appropriate HTTP header.
- Furthermore, the attribute should not be used and can be removed without warning in future versions of SearchGuard.
- Multi-tenancy cannot be switched off without data lost.
- Legacy Multi-Tenancy configuration should not be used with Search Guard FLX 2.0.0 or newer.
- Private tenants are not supported; data associated with private tenants will not be migrated to version 2.0.0.
The system administration before usage multi-tenancy implementation provided with SearchGuard 2.x.x should consider if the above limitations are acceptable.
Fixing curl issues
If you experience problems with curl commands see Fixing curl first before reporting any issues.
Additional resources