diff --git a/_includes/code/python/howto.configure.rbac.permissions.py b/_includes/code/python/howto.configure.rbac.permissions.py
index baeab65d3..383cf4101 100644
--- a/_includes/code/python/howto.configure.rbac.permissions.py
+++ b/_includes/code/python/howto.configure.rbac.permissions.py
@@ -11,7 +11,7 @@
# Use custom port defined in tests/docker-compose-rbac.yml (without showing the user)
port=8580,
grpc_port=50551,
- auth_credentials=Auth.api_key("admin-key")
+ auth_credentials=Auth.api_key("user-a-key")
)
def reset_user(user: str, client: WeaviateClient):
@@ -25,7 +25,7 @@ def reset_user(user: str, client: WeaviateClient):
# =================================================================
# Clean slate
-reset_user("other-user", client=admin_client)
+reset_user("user-c", client=admin_client)
admin_client.roles.delete("rw_role_target_collections") # delete if exists
# START ReadWritePermissionDefinition
@@ -52,11 +52,11 @@ def reset_user(user: str, client: WeaviateClient):
# Create a new role and assign it to a user
admin_client.roles.create(role_name="rw_role_target_collections", permissions=admin_permissions)
-admin_client.roles.assign_to_user(role_names="rw_role_target_collections", user="other-user")
+admin_client.roles.assign_to_user(role_names="rw_role_target_collections", user="user-c")
# END ReadWritePermissionDefinition
# ===== TEST ===== basic checks to see if the role was created
-user_permissions = admin_client.roles.by_user("other-user")
+user_permissions = admin_client.roles.by_user("user-c")
assert "rw_role_target_collections" in user_permissions.keys()
assert user_permissions["rw_role_target_collections"].collections_permissions[0].collection == "TargetCollection_*"
@@ -67,7 +67,7 @@ def reset_user(user: str, client: WeaviateClient):
# =================================================================
# Clean slate
-reset_user("other-user", client=admin_client)
+reset_user("user-c", client=admin_client)
admin_client.roles.delete("viewer_role_target_collections") # delete if exists
# START ViewerPermissionDefinition
@@ -82,11 +82,41 @@ def reset_user(user: str, client: WeaviateClient):
# Create a new role and assign it to a user
admin_client.roles.create(role_name="viewer_role_target_collections", permissions=viewer_permissions)
-admin_client.roles.assign_to_user(role_names="viewer_role_target_collections", user="other-user")
+admin_client.roles.assign_to_user(role_names="viewer_role_target_collections", user="user-c")
# END ViewerPermissionDefinition
+# Clean slate - delete `tenant_manager` role if exists
+admin_client.roles.delete("tenant_manager")
+
+# START MTPermissionsExample
+permissions = [
+ Permissions.collections(
+ collection="TargetCollection_*",
+ create_collection=True,
+ read_config=True,
+ update_config=True,
+ delete_collection=True
+ ),
+ # Without the below permission, the user would not
+ # be able to create tenants in collections starting with "TargetCollection_"
+ Permissions.tenants(
+ collection="TargetCollection_*",
+ create=True,
+ read=True,
+ update=True,
+ delete=False
+ )
+]
+
+admin_client.roles.create(
+ role_name="tenant_manager", permissions=permissions
+)
+
+admin_client.roles.assign_to_user(role_names="tenant_manager", user="user-c")
+# END MTPermissionsExample
+
# ===== TEST ===== basic checks to see if the role was created
-user_permissions = admin_client.roles.by_user("other-user")
+user_permissions = admin_client.roles.by_user("user-c")
assert "viewer_role_target_collections" in user_permissions.keys()
assert user_permissions["viewer_role_target_collections"].collections_permissions[0].collection == "TargetCollection_*"
diff --git a/_includes/code/python/howto.configure.rbac.roles.py b/_includes/code/python/howto.configure.rbac.roles.py
index fc2df06eb..d092aa5f4 100644
--- a/_includes/code/python/howto.configure.rbac.roles.py
+++ b/_includes/code/python/howto.configure.rbac.roles.py
@@ -11,14 +11,17 @@
port=8580,
grpc_port=50551,
# START AdminClient
- auth_credentials=Auth.api_key("admin-key")
+ auth_credentials=Auth.api_key("user-a-key")
)
# END AdminClient
-jane_client = weaviate.connect_to_local(
- port=8580, grpc_port=50551, auth_credentials=Auth.api_key("jane-key")
+custom_user_client = weaviate.connect_to_local(
+ port=8580, grpc_port=50551, auth_credentials=Auth.api_key("user-c-key")
)
+admin_client.roles.delete("devrel")
+admin_client.roles.delete("devrel-admin")
+
# # START CreateRole
# admin_client.roles.create(role_name="devrel")
# # END CreateRole
@@ -82,16 +85,16 @@
# START AssignRole
-admin_client.roles.assign_to_user(role_names="devrel", user="jane-doe")
+admin_client.roles.assign_to_user(role_names="devrel", user="user-c")
# END AssignRole
-assert "devrel" in admin_client.roles.by_user(user="jane-doe")
+assert "devrel" in admin_client.roles.by_user(user="user-c")
# START ListCurrentUserRoles
print(admin_client.roles.of_current_user())
# END ListCurrentUserRoles
# START ListUserRoles
-user_roles = admin_client.roles.by_user(user="jane-doe")
+user_roles = admin_client.roles.by_user(user="user-c")
for role in user_roles:
print(role)
@@ -112,7 +115,7 @@
for user in assigned_users:
print(user)
# END AssignedUsers
-assert "jane-doe" in assigned_users
+assert "user-c" in assigned_users
# START ListAllRoles
all_roles = admin_client.roles.list_all()
@@ -140,13 +143,13 @@
# END RemovePermissions
# START RevokeRoles
-admin_client.roles.revoke_from_user(role_names=["devrel"], user="jane-doe")
+admin_client.roles.revoke_from_user(role_names=["devrel"], user="user-c")
# END RevokeRoles
-assert "devrel" not in admin_client.roles.by_user(user="jane-doe")
+assert "devrel" not in admin_client.roles.by_user(user="user-c")
# START DeleteRole
admin_client.roles.delete(role_name="devrel")
# END DeleteRole
admin_client.close()
-jane_client.close()
+custom_user_client.close()
diff --git a/developers/weaviate/configuration/authentication.md b/developers/weaviate/configuration/authentication.md
index f123ab435..6a6788650 100644
--- a/developers/weaviate/configuration/authentication.md
+++ b/developers/weaviate/configuration/authentication.md
@@ -97,10 +97,10 @@ services:
AUTHENTICATION_APIKEY_ENABLED: 'true'
# List one or more keys in plaintext separated by commas. Each key corresponds to a specific user identity below.
- AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'viewer-key,admin-key'
+ AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'user-a-key,user-b-key'
# List one or more user identities, separated by commas. Each identity corresponds to a specific key above.
- AUTHENTICATION_APIKEY_USERS: 'viewer-user,admin-user'
+ AUTHENTICATION_APIKEY_USERS: 'user-a,user-b'
```
This configuration:
@@ -127,13 +127,13 @@ authentication:
# List one or more keys in plaintext separated by commas. Each key corresponds to a specific user identity below.
allowed_keys:
- - admin-key
- - viewer-key
+ - user-a-key
+ - user-b-key
# List one or more user identities, separated by commas. Each identity corresponds to a specific key above.
users:
- - admin-user
- - viewer-user
+ - user-a
+ - user-b
```
This configuration:
diff --git a/developers/weaviate/configuration/authorization.md b/developers/weaviate/configuration/authorization.md
index 962eaa661..7366f8856 100644
--- a/developers/weaviate/configuration/authorization.md
+++ b/developers/weaviate/configuration/authorization.md
@@ -135,8 +135,8 @@ services:
# OIDC access can also be used with RBAC
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'false'
AUTHENTICATION_APIKEY_ENABLED: 'true'
- AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'viewer-key,admin-key,other-key'
- AUTHENTICATION_APIKEY_USERS: 'viewer-user,admin-user,other-user'
+ AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'user-a-key,user-b-key,user-c-key'
+ AUTHENTICATION_APIKEY_USERS: 'user-a,user-b,user-c'
# Authorization configuration
# Enable RBAC
@@ -146,17 +146,17 @@ services:
# This assumes that the relevant user has been authenticated and identified
#
# You MUST define at least one admin user
- AUTHORIZATION_ADMIN_USERS: 'admin-user'
- AUTHORIZATION_VIEWER_USERS: 'viewer-user'
+ AUTHORIZATION_ADMIN_USERS: 'user-a'
+ AUTHORIZATION_VIEWER_USERS: 'user-b'
```
This configuration:
- Enables RBAC
-- Configures `admin-user` as a user with built-in admin permissions
-- Configures `viewer-user` as a user with built-in viewer permissions
-- Configures `other-user` as a user with no built-in permissions
+- Configures `user-a` as a user with built-in admin permissions
+- Configures `user-b` as a user with built-in viewer permissions
+- Configures `user-c` as a user with no built-in permissions
-The `other-user` can now be assigned custom roles and permissions using the [RBAC Roles API](./roles.md).
+The `user-c` can now be assigned custom roles and permissions using the [RBAC Roles API](./roles.md).
### RBAC: Kubernetes
@@ -170,13 +170,13 @@ authentication:
apikey:
enabled: true
allowed_keys:
- - admin-key
- - viewer-key
- - other-key
+ - user-a-key
+ - user-b-key
+ - user-c-key
users:
- - admin-user
- - viewer-user
- - other-user
+ - user-a
+ - user-b
+ - user-c
# Authorization configuration
authorization:
@@ -188,18 +188,18 @@ authorization:
#
# You MUST define at least one admin user
admins:
- - admin-user
+ - user-a
viewers:
- - viewer-user
+ - user-b
```
This configuration:
- Enables RBAC
-- Configures `admin-user` as a user with built-in admin permissions
-- Configures `viewer-user` as a user with built-in viewer permissions
-- Configures `other-user` as a user with no built-in permissions
+- Configures `user-a` as a user with built-in admin permissions
+- Configures `user-b` as a user with built-in viewer permissions
+- Configures `user-c` as a user with no built-in permissions
-The `other-user` can now be assigned custom roles and permissions using the [RBAC Roles API](./roles.md).
+The `user-c` can now be assigned custom roles and permissions using the [RBAC Roles API](./roles.md).
## Admin list
@@ -223,8 +223,8 @@ services:
# OIDC access can also be used with RBAC
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'false'
AUTHENTICATION_APIKEY_ENABLED: 'true'
- AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'viewer-key,admin-key,other-key'
- AUTHENTICATION_APIKEY_USERS: 'viewer-user,admin-user,other-user'
+ AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'user-a-key,user-b-key,user-c-key'
+ AUTHENTICATION_APIKEY_USERS: 'user-a,user-b,user-c'
# Authorization configuration
# Enable admin list
@@ -234,16 +234,16 @@ services:
# This assumes that the relevant user has been authenticated and identified
#
# You MUST define at least one admin user
- AUTHORIZATION_ADMINLIST_USERS: 'admin-user'
- AUTHORIZATION_ADMINLIST_READONLY_USERS: 'viewer-user'
+ AUTHORIZATION_ADMINLIST_USERS: 'user-a'
+ AUTHORIZATION_ADMINLIST_READONLY_USERS: 'user-b'
```
This configuration:
- Enables Admin list authorization
-- Configures `admin-user` as a user with built-in admin permissions
-- Configures `viewer-user` as a user with built-in viewer permissions
+- Configures `user-a` as a user with built-in admin permissions
+- Configures `user-b` as a user with built-in viewer permissions
-Note that in this configuration, `other-user` has no permissions.
+Note that in this configuration, `user-c` has no permissions.
### Admin list: Kubernetes
@@ -257,13 +257,13 @@ authentication:
apikey:
enabled: true
allowed_keys:
- - admin-key
- - viewer-key
- - other-key
+ - user-a-key
+ - user-b-key
+ - user-c-key
users:
- - admin-user
- - viewer-user
- - other-user
+ - user-a
+ - user-b
+ - user-c
# Authorization configuration
authorization:
@@ -276,9 +276,9 @@ authorization:
#
# You MUST define at least one admin user
users:
- - admin-user
+ - user-a
read_only_users:
- - viewer-user
+ - user-b
```
### Anonymous users
@@ -305,11 +305,11 @@ services:
# Configure admin user API key
AUTHORIZATION_ADMINLIST_ENABLED: 'true'
- AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'admin-key'
- AUTHENTICATION_APIKEY_USERS: 'admin-user'
+ AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'user-a-key'
+ AUTHENTICATION_APIKEY_USERS: 'user-a'
- # Enable admin list and provide admin access to "admin-user" only
- AUTHORIZATION_ADMINLIST_USERS: 'admin-user'
+ # Enable admin list and provide admin access to "user-a" only
+ AUTHORIZATION_ADMINLIST_USERS: 'user-a'
# Provide read-only access to anonymous users
AUTHORIZATION_ADMINLIST_READONLY_USERS: 'anonymous'
```
@@ -329,17 +329,17 @@ authentication:
apikey:
enabled: true
allowed_keys:
- - admin-key
+ - user-a-key
users:
- - admin-user
+ - user-a
authorization:
- # Enable admin list and provide admin access to "admin-user" only
+ # Enable admin list and provide admin access to "user-a" only
admin_list:
# Enable admin list
enabled: true
users:
- - admin-user
+ - user-a
# Provide read-only access to anonymous users
read_only_users:
- anonymous
diff --git a/developers/weaviate/configuration/roles.md b/developers/weaviate/configuration/roles.md
index 57ec52e8b..af6b88006 100644
--- a/developers/weaviate/configuration/roles.md
+++ b/developers/weaviate/configuration/roles.md
@@ -69,6 +69,9 @@ Permissions can be defined for the following resources:
1. **Collections** (collection definitions only, data object permissions are separate)
- Create, read, update, and delete collection definitions
+1. **Tenants** ([available from `v1.28.3`](#collection-and-tenant-permissions))
+ - Create, read, update, and delete tenants
+
1. **Data Objects**
- Read, write, update, and delete objects
@@ -109,6 +112,18 @@ Many permissions require a collection name filter, to specify which collections
In thi case, `"*"` acts as a multi-character wildcard. As an example, setting a permission with `"Test_*"` as the collection filter would apply that permission to all collections that start with `Test_`. Or, setting a permission with `"*"` as the collection filter would apply that permission to all available collections.
+### Collection and tenant permissions
+
+:::caution Breaking change introduced in `v1.28.3`
+This change was introduced in `v1.28.3` during the technical preview phase. In `v1.28.0` - `v1.28.2`, a collection level permission would cascade to confer permissions the equivalent tenant-level operations. This behavior was changed in `v1.28.3` to require explicit tenant-level permissions for tenant operations, for operations such as creating a tenant, updating tenant status, and so on.
+:::
+
+A collection permission is independent of tenant permissions.
+
+To have permissions to operate on a tenant that belongs to a collection, the user must have the appropriate tenant-level permissions for that collection. Collection-level permissions, such as that to create collections, do not confer the equivalent tenant-level permissions, such as that to create tenants for that collection.
+
+For example, to create a tenant in a collection called "Test_Collection", the user must have permission to "create" tenants in that collection. This is separate from the permission to create a collection called "Test_Collection".
+
## Example permission sets
### Read and write permissions
@@ -193,6 +208,47 @@ This confers viewer permissions for collections starting with `TargetCollection_
+### Example tenant permissions
+
+This confers permissions to manage collections starting with `TargetCollection_`, and to create, read, and update tenants in the same collection.
+
+
+
+
+
+
+
+
+
+```ts
+// TS support coming soon
+```
+
+
+
+
+
+```go
+// Go support coming soon
+```
+
+
+
+
+
+```java
+// Java support coming soon
+```
+
+
+
+
+
import RolePyCode from '!!raw-loader!/_includes/code/python/howto.configure.rbac.roles.py';
## Role management
@@ -419,7 +475,7 @@ This example removes from the "devrel" role permissions to:
A custom user can have any number of roles assigned to them (including none). The role can be a predefined role (e.g. `viewer`) or a custom role.
-This example assigns the custom "devrel" role to "jane-doe".
+This example assigns the custom "devrel" role to "user-c".
@@ -745,7 +801,7 @@ Deleting a role will remove it from the system, and revoke the associated permis
You can revoke one or more roles from a specific user.
-This examples revokes "role-1" and "role-2" from the user "jane-doe".
+This examples revokes "role-1" and "role-2" from the user "user-c".
diff --git a/tests/docker-compose-anon-2.yml b/tests/docker-compose-anon-2.yml
index 1a078ed14..880af62e7 100644
--- a/tests/docker-compose-anon-2.yml
+++ b/tests/docker-compose-anon-2.yml
@@ -8,7 +8,7 @@ services:
- '8080'
- --scheme
- http
- image: cr.weaviate.io/semitechnologies/weaviate:1.28.2
+ image: cr.weaviate.io/semitechnologies/weaviate:1.28.3
ports:
- 8090:8080
- 50061:50051
diff --git a/tests/docker-compose-anon-bind.yml b/tests/docker-compose-anon-bind.yml
index 318a51f27..a9f8e3eea 100644
--- a/tests/docker-compose-anon-bind.yml
+++ b/tests/docker-compose-anon-bind.yml
@@ -8,7 +8,7 @@ services:
- '8080'
- --scheme
- http
- image: cr.weaviate.io/semitechnologies/weaviate:1.28.2
+ image: cr.weaviate.io/semitechnologies/weaviate:1.28.3
ports:
- 8380:8080
- 50351:50051
diff --git a/tests/docker-compose-anon-clip.yml b/tests/docker-compose-anon-clip.yml
index bac2cfe8d..fb0224132 100644
--- a/tests/docker-compose-anon-clip.yml
+++ b/tests/docker-compose-anon-clip.yml
@@ -8,7 +8,7 @@ services:
- '8080'
- --scheme
- http
- image: cr.weaviate.io/semitechnologies/weaviate:1.28.2
+ image: cr.weaviate.io/semitechnologies/weaviate:1.28.3
ports:
- 8280:8080
- 50251:50051
diff --git a/tests/docker-compose-anon-offload.yml b/tests/docker-compose-anon-offload.yml
index aee4d7bd7..f4d07b370 100644
--- a/tests/docker-compose-anon-offload.yml
+++ b/tests/docker-compose-anon-offload.yml
@@ -8,7 +8,7 @@ services:
- '8080'
- --scheme
- http
- image: cr.weaviate.io/semitechnologies/weaviate:1.28.2
+ image: cr.weaviate.io/semitechnologies/weaviate:1.28.3
ports:
- 8080:8080
- 50051:50051
diff --git a/tests/docker-compose-anon.yml b/tests/docker-compose-anon.yml
index 70ca842eb..ac907a49b 100644
--- a/tests/docker-compose-anon.yml
+++ b/tests/docker-compose-anon.yml
@@ -8,7 +8,7 @@ services:
- '8080'
- --scheme
- http
- image: cr.weaviate.io/semitechnologies/weaviate:1.28.2
+ image: cr.weaviate.io/semitechnologies/weaviate:1.28.3
ports:
- 8080:8080
- 50051:50051
diff --git a/tests/docker-compose-rbac.yml b/tests/docker-compose-rbac.yml
index 48f5966b1..26b523e23 100644
--- a/tests/docker-compose-rbac.yml
+++ b/tests/docker-compose-rbac.yml
@@ -8,7 +8,7 @@ services:
- '8080'
- --scheme
- http
- image: cr.weaviate.io/semitechnologies/weaviate:1.28.2
+ image: cr.weaviate.io/semitechnologies/weaviate:1.28.3
ports:
- 8580:8080
- 50551:50051
@@ -24,9 +24,9 @@ services:
# AuthN and AuthZ settings
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'false'
AUTHENTICATION_APIKEY_ENABLED: 'true'
- AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'viewer-key,admin-key,other-user,jane-key'
- AUTHENTICATION_APIKEY_USERS: 'viewer-user,admin-user,other-user,jane-doe'
+ AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'user-a-key,user-b-key,user-c-key'
+ AUTHENTICATION_APIKEY_USERS: 'user-a,user-b,user-c'
AUTHORIZATION_ENABLE_RBAC: 'true'
- AUTHORIZATION_ADMIN_USERS: 'admin-user'
- AUTHORIZATION_VIEWER_USERS: 'viewer-user'
+ AUTHORIZATION_ADMIN_USERS: 'user-a'
+ AUTHORIZATION_VIEWER_USERS: 'user-b'
...
diff --git a/tests/docker-compose-three-nodes.yml b/tests/docker-compose-three-nodes.yml
index c6f775aa5..3e1742c00 100644
--- a/tests/docker-compose-three-nodes.yml
+++ b/tests/docker-compose-three-nodes.yml
@@ -8,7 +8,7 @@ services:
- '8080'
- --scheme
- http
- image: cr.weaviate.io/semitechnologies/weaviate:1.28.2
+ image: cr.weaviate.io/semitechnologies/weaviate:1.28.3
restart: on-failure:0
ports:
- "8180:8080"
@@ -36,7 +36,7 @@ services:
- '8080'
- --scheme
- http
- image: cr.weaviate.io/semitechnologies/weaviate:1.28.2
+ image: cr.weaviate.io/semitechnologies/weaviate:1.28.3
restart: on-failure:0
ports:
- "8181:8080"
@@ -65,7 +65,7 @@ services:
- '8080'
- --scheme
- http
- image: cr.weaviate.io/semitechnologies/weaviate:1.28.2
+ image: cr.weaviate.io/semitechnologies/weaviate:1.28.3
restart: on-failure:0
ports:
- "8182:8080"
diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml
index 6c33db38c..532961cbf 100644
--- a/tests/docker-compose.yml
+++ b/tests/docker-compose.yml
@@ -8,7 +8,7 @@ services:
- '8080'
- --scheme
- http
- image: cr.weaviate.io/semitechnologies/weaviate:1.28.2
+ image: cr.weaviate.io/semitechnologies/weaviate:1.28.3
ports:
- 8099:8080
- 50052:50051