Skip to content

Commit

Permalink
Add backup permissions to Roles and filter on collection.
Browse files Browse the repository at this point in the history
Up to know backup permissions could be filter on backend
however it has been decided to filter on collection name.
  • Loading branch information
jfrancoa committed Nov 28, 2024
1 parent 43e12ac commit d5572d6
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 23 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ env:
WEAVIATE_125: 1.25.24
WEAVIATE_126: 1.26.8
WEAVIATE_127: 1.27.1
WEAVIATE_128: 1.28.0-dev-86bd591
WEAVIATE_128: 1.28.0-dev-a6402ab

jobs:
lint-and-format:
Expand Down Expand Up @@ -418,4 +418,4 @@ jobs:
with:
generate_release_notes: true
draft: true
files: dist/*.whl
files: dist/*.whl
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ repos:
- id: trailing-whitespace

- repo: https://github.com/myint/autoflake
rev: v1.4
rev: v2.2.1 # autoflake v2.2.1 is the latest version that supports Python 3.12
hooks:
- id: autoflake
args: [--in-place, --remove-all-unused-imports, --exclude=weaviate/proto/*]
Expand All @@ -36,13 +36,13 @@ repos:
]
files: '^weaviate/collections'

- repo: local
hooks:
- repo: local
hooks:
- id: mypy
name: mypy
entry: ./run-mypy.sh
language: python
language_version: "3.11"
language_version: "3.12"
# use require_serial so that script
# is only called once per commit
require_serial: true
Expand Down
23 changes: 20 additions & 3 deletions integration/test_rbac.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
Role,
ConfigPermission,
RolesPermission,
BackupsPermission,
)

RBAC_PORTS = (8092, 50063)
Expand All @@ -27,6 +28,7 @@
],
roles_permissions=None,
data_permissions=None,
backups_permissions=None,
),
),
(
Expand All @@ -38,6 +40,21 @@
config_permissions=None,
roles_permissions=[RolesPermission(role="*", action=RBAC.actions.roles.MANAGE)],
data_permissions=None,
backups_permissions=None,
),
),
(
RBAC.permissions.backups.manage(collection="Test"),
Role(
name="ManageAllBackups",
cluster_actions=None,
users_permissions=None,
config_permissions=None,
roles_permissions=None,
data_permissions=None,
backups_permissions=[
BackupsPermission(collection="Test", action=RBAC.actions.backups.MANAGE)
],
),
),
],
Expand All @@ -61,7 +78,7 @@ def test_add_permissions_to_existing(client_factory: ClientFactory) -> None:
with client_factory(ports=RBAC_PORTS, auth_credentials=RBAC_AUTH_CREDS) as client:
if client._connection._weaviate_version.is_lower_than(1, 28, 0):
pytest.skip("This test requires Weaviate 1.28.0 or higher")
role_name = "ExistingRole"
role_name = "ExistingRolePermissions"
try:
client.roles.create(
name=role_name,
Expand Down Expand Up @@ -97,7 +114,7 @@ def test_upsert_permissions(client_factory: ClientFactory) -> None:
with client_factory(ports=RBAC_PORTS, auth_credentials=RBAC_AUTH_CREDS) as client:
if client._connection._weaviate_version.is_lower_than(1, 28, 0):
pytest.skip("This test requires Weaviate 1.28.0 or higher")
role_name = "ExistingRole"
role_name = "ExistingRoleUpsert"
try:
client.roles.add_permissions(
permissions=[
Expand All @@ -119,7 +136,7 @@ def test_downsert_permissions(client_factory: ClientFactory) -> None:
with client_factory(ports=RBAC_PORTS, auth_credentials=RBAC_AUTH_CREDS) as client:
if client._connection._weaviate_version.is_lower_than(1, 28, 0):
pytest.skip("This test requires Weaviate 1.28.0 or higher")
role_name = "ExistingRole"
role_name = "ExistingRoleDownsert"
try:
client.roles.create(
name=role_name,
Expand Down
38 changes: 27 additions & 11 deletions weaviate/rbac/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


class PermissionBackup(TypedDict):
backend: str
collection: str


class WeaviatePermission(TypedDict):
Expand Down Expand Up @@ -99,7 +99,7 @@ def _to_weaviate(self) -> WeaviatePermission:
return {
"action": self.action,
"backup": {
"backend": "*",
"collection": "*",
},
"collection": self.collection,
"role": "*",
Expand All @@ -116,7 +116,7 @@ def _to_weaviate(self) -> WeaviatePermission:
return {
"action": self.action,
"backup": {
"backend": "*",
"collection": "*",
},
"collection": "*",
"role": self.role,
Expand All @@ -133,7 +133,7 @@ def _to_weaviate(self) -> WeaviatePermission:
return {
"action": self.action,
"backup": {
"backend": "*",
"collection": "*",
},
"user": self.user,
"role": "*",
Expand All @@ -143,7 +143,7 @@ def _to_weaviate(self) -> WeaviatePermission:


class _BackupsPermission(_Permission):
backend: str
collection: str
action: BackupsAction

def _to_weaviate(self) -> WeaviatePermission:
Expand All @@ -154,7 +154,7 @@ def _to_weaviate(self) -> WeaviatePermission:
"user": "*",
"collection": "*",
"backup": {
"backend": self.backend,
"collection": self.collection,
},
}

Expand All @@ -166,7 +166,7 @@ def _to_weaviate(self) -> WeaviatePermission:
return {
"action": self.action,
"backup": {
"backend": "*",
"collection": "*",
},
"role": "*",
"tenant": "*",
Expand All @@ -184,7 +184,7 @@ def _to_weaviate(self) -> WeaviatePermission:
return {
"action": self.action,
"backup": {
"backend": "*",
"collection": "*",
},
"collection": self.collection,
"role": "*",
Expand Down Expand Up @@ -218,6 +218,12 @@ class UsersPermission:
action: UsersAction


@dataclass
class BackupsPermission:
collection: str
action: BackupsAction


@dataclass
class Role:
name: str
Expand All @@ -226,6 +232,7 @@ class Role:
data_permissions: Optional[List[DataPermission]]
roles_permissions: Optional[List[RolesPermission]]
users_permissions: Optional[List[UsersPermission]]
backups_permissions: Optional[List[BackupsPermission]]

@classmethod
def _from_weaviate_role(cls, role: WeaviateRole) -> "Role":
Expand All @@ -234,6 +241,7 @@ def _from_weaviate_role(cls, role: WeaviateRole) -> "Role":
config_permissions: List[ConfigPermission] = []
roles_permissions: List[RolesPermission] = []
data_permissions: List[DataPermission] = []
backups_permissions: List[BackupsPermission] = []

for permission in role["permissions"]:
if permission["action"] in ClusterAction.values():
Expand Down Expand Up @@ -265,6 +273,13 @@ def _from_weaviate_role(cls, role: WeaviateRole) -> "Role":
action=DataAction(permission["action"]),
)
)
elif permission["action"] in BackupsAction.values():
backups_permissions.append(
BackupsPermission(
collection=permission["backup"]["collection"],
action=BackupsAction(permission["action"]),
)
)
else:
raise ValueError(
f"The actions of role {role['name']} are mixed between levels somehow!"
Expand All @@ -275,7 +290,8 @@ def _from_weaviate_role(cls, role: WeaviateRole) -> "Role":
users_permissions=up if len(up := users_permissions) > 0 else None,
config_permissions=cp if len(cp := config_permissions) > 0 else None,
roles_permissions=rp if len(rp := roles_permissions) > 0 else None,
data_permissions=(dp if len(dp := data_permissions) > 0 else None),
data_permissions=dp if len(dp := data_permissions) > 0 else None,
backups_permissions=bp if len(bp := backups_permissions) > 0 else None,
)


Expand Down Expand Up @@ -354,8 +370,8 @@ def manage() -> _ClusterPermission:

class _BackupsFactory:
@staticmethod
def manage(*, backend: Optional[str] = None) -> _BackupsPermission:
return _BackupsPermission(backend=backend or "*", action=BackupsAction.MANAGE)
def manage(*, collection: Optional[str] = None) -> _BackupsPermission:
return _BackupsPermission(collection=collection or "*", action=BackupsAction.MANAGE)


class ActionsFactory:
Expand Down
6 changes: 3 additions & 3 deletions weaviate/rbac/sync.pyi
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from typing import List, Optional, Union
from typing import Dict, List, Optional, Union
from weaviate.rbac.roles import _RolesBase
from weaviate.rbac.models import Permissions, Role, User

class _Roles(_RolesBase):
def list_all(self) -> List[Role]: ...
def by_name(self, role: str) -> Optional[Role]: ...
def by_user(self, user: str) -> List[Role]: ...
def users(self, role: str) -> List[User]: ...
def by_user(self, user: str) -> Dict[str, Role]: ...
def users(self, role: str) -> Dict[str, User]: ...
def delete(self, role: str) -> None: ...
def create(self, *, name: str, permissions: Permissions) -> Role: ...
def assign(self, *, roles: Union[str, List[str]], user: str) -> None: ...
Expand Down

0 comments on commit d5572d6

Please sign in to comment.