mirror of
https://github.com/sartography/spiff-arena.git
synced 2025-02-10 08:26:38 +00:00
Feature/add support permissions (#445)
* added support perm macro which removes secrets perms w/ burnettk * support perm macro inherits from basic now and updated docs on permissions to be more accurate w/ burnettk --------- Co-authored-by: jasquat <jasquat@users.noreply.github.com>
This commit is contained in:
parent
a9b6f05e14
commit
29620cb17f
@ -4,74 +4,52 @@ The permission URL, or target URI, refers to the specific endpoint or resource t
|
|||||||
|
|
||||||
- **PG:** [process_group_identifier]: Applies to the specified process group, including all sub process groups and process models.
|
- **PG:** [process_group_identifier]: Applies to the specified process group, including all sub process groups and process models.
|
||||||
- **PM:** [process_model_identifier]: Applies to the specified process model.
|
- **PM:** [process_model_identifier]: Applies to the specified process model.
|
||||||
- **BASIC:** Provides basic access to complete tasks and use the site.
|
- **BASIC:** Allows basic access to complete tasks and use the site.
|
||||||
- **ELEVATED:** Enables operations that require elevated permissions.
|
- **SUPPORT:** BASIC permissions and add significant administrative permissions.
|
||||||
- **ALL:** Grants access to all API endpoints, providing admin-like permissions.
|
- **ELEVATED:** Includes SUPPORT permissions and adds the ability to view and modify secrets. Does not include the ability to view or modify process groups and process models.
|
||||||
|
- **ALL:** Grants access to all API endpoints, with no limitations.
|
||||||
|
|
||||||
```{admonition} Note
|
```{admonition} Note
|
||||||
An asterisk (*) can be used as a wildcard to give access to everything within a specific category. For example, "/process-models/", allows access to all resources related to process models.
|
An asterisk (*) can be used as a wildcard to give access to everything within a specific category. For example, `/process-models/*`, allows access to all resources related to process models.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This functionality is implemented in [authorization service.py](https://github.com/sartography/spiff-arena/blob/main/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py).
|
||||||
|
|
||||||
|
(pg)=
|
||||||
## PG
|
## PG
|
||||||
|
|
||||||
Process Groups permissions controls access rights granted to users or entities within that particular process model. By assigning permissions to process groups, you can determine what actions or operations users can perform within those groups.
|
Process Groups permissions controls access rights granted to users or entities within the given process group.
|
||||||
|
|
||||||
[View GIT Repository - BASIC](https://github.com/sartography/spiff-arena/blob/main/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py#L557)
|
|
||||||
|
|
||||||
```python
|
|
||||||
def set_process_model_permissions(cls, target: str, permission_set: str) -> list[PermissionToAssign]:
|
|
||||||
```
|
|
||||||
|
|
||||||
|
(pm)=
|
||||||
## PM
|
## PM
|
||||||
|
|
||||||
These permissions relates to process models. It defines the permissions and access rights assigned to users or entities specifically within a given process model.
|
These permissions relate to process models, and assigns permissions and access rights to users or entities specifically within a given process model.
|
||||||
|
|
||||||
[View GIT Repository - BASIC](https://github.com/sartography/spiff-arena/blob/main/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py#L574)
|
|
||||||
|
|
||||||
```python
|
|
||||||
def set_process_group_permissions(cls, target: str, permission_set: str) -> list[PermissionToAssign]:
|
|
||||||
```
|
|
||||||
|
|
||||||
## BASIC
|
## BASIC
|
||||||
|
|
||||||
These permissions cover basic actions such as creating users and process instances, checking user existence, and reading various entities like process groups, models, and tasks.
|
These permissions cover basic actions such as signing in to the site and completing tasks that are assigned to you.
|
||||||
|
|
||||||
[View GIT Repository - BASIC](https://github.com/sartography/spiff-arena/blob/main/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py#L494)
|
## SUPPORT
|
||||||
|
|
||||||
```python
|
These permissions are significant, allowing support personnel to debug process instances and take corrective action when errors occur.
|
||||||
def set_basic_permissions(cls) -> list[PermissionToAssign]:
|
In typical scenarios, a user with SUPPORT permissions would also be assigned access to view or modify process groups and models.
|
||||||
```
|
See [PG](#pg) and [PM](#pm).
|
||||||
|
|
||||||
## ELEVATED
|
## ELEVATED
|
||||||
|
|
||||||
These permissions cover basic actions such as creating users and process instances, checking user existence, and reading various entities like process groups, models, and tasks.
|
A user with elevated permissions can do anything on the site except interact with process models.
|
||||||
|
In typical scenarios, a user with ELEVATED permissions would also be assigned access to view or modify process groups and models.
|
||||||
[View GIT Repository - BASIC](https://github.com/sartography/spiff-arena/blob/main/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py#L494)
|
|
||||||
|
|
||||||
```python
|
|
||||||
def explode_permissions(cls, permission_set: str, target: str) -> list[PermissionToAssign]:
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## ALL
|
## ALL
|
||||||
|
|
||||||
The "ALL" permission grants unrestricted access to all API endpoints. It essentially provides administrator-like permissions, allowing the user to perform any action or operation available within the system.
|
The "ALL" permission grants unrestricted access to all API endpoints.
|
||||||
|
It provides administrator-level permissions, allowing the user to perform any action or operation available within the system.
|
||||||
```python
|
|
||||||
elif target == "ALL":
|
|
||||||
for permission in permissions:
|
|
||||||
permissions_to_assign.append(PermissionToAssign(permission=permission, target_uri="/*"))
|
|
||||||
elif target.startswith("/"):
|
|
||||||
for permission in permissions:
|
|
||||||
permissions_to_assign.append(PermissionToAssign(permission=permission, target_uri=target))
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### ALL URLs
|
### ALL URLs
|
||||||
|
|
||||||
```python
|
% use bash syntax here to avoid syntax highlighting. otherwise it gets highlighted as if it's python
|
||||||
/active-users/unregister/{last_visited_identifier}:
|
```bash
|
||||||
|
/active-users/unregister/{last_visited_identifier}:
|
||||||
/active-users/updates/{last_visited_identifier}:
|
/active-users/updates/{last_visited_identifier}:
|
||||||
/authentication_callback/{service}/{auth_method}:
|
/authentication_callback/{service}/{auth_method}:
|
||||||
/authentications:
|
/authentications:
|
||||||
|
@ -530,7 +530,20 @@ class AuthorizationService:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_elevated_permissions(cls) -> list[PermissionToAssign]:
|
def set_elevated_permissions(cls) -> list[PermissionToAssign]:
|
||||||
permissions_to_assign: list[PermissionToAssign] = []
|
"""This is basically /* without write access to Process Groups and Process Models.
|
||||||
|
|
||||||
|
Useful for admin-like permissions on readonly environments like a production environment.
|
||||||
|
"""
|
||||||
|
permissions_to_assign = cls.set_support_permissions()
|
||||||
|
for permission in ["create", "read", "update", "delete"]:
|
||||||
|
permissions_to_assign.append(PermissionToAssign(permission=permission, target_uri="/secrets/*"))
|
||||||
|
|
||||||
|
return permissions_to_assign
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_support_permissions(cls) -> list[PermissionToAssign]:
|
||||||
|
"""Just like elevated permissions minus access to secrets."""
|
||||||
|
permissions_to_assign = cls.set_basic_permissions()
|
||||||
for process_instance_action in ["resume", "terminate", "suspend", "reset"]:
|
for process_instance_action in ["resume", "terminate", "suspend", "reset"]:
|
||||||
permissions_to_assign.append(
|
permissions_to_assign.append(
|
||||||
PermissionToAssign(permission="create", target_uri=f"/process-instance-{process_instance_action}/*")
|
PermissionToAssign(permission="create", target_uri=f"/process-instance-{process_instance_action}/*")
|
||||||
@ -562,7 +575,6 @@ class AuthorizationService:
|
|||||||
|
|
||||||
for permission in ["create", "read", "update", "delete"]:
|
for permission in ["create", "read", "update", "delete"]:
|
||||||
permissions_to_assign.append(PermissionToAssign(permission=permission, target_uri="/process-instances/*"))
|
permissions_to_assign.append(PermissionToAssign(permission=permission, target_uri="/process-instances/*"))
|
||||||
permissions_to_assign.append(PermissionToAssign(permission=permission, target_uri="/secrets/*"))
|
|
||||||
|
|
||||||
permissions_to_assign.append(PermissionToAssign(permission="read", target_uri="/data-stores/*"))
|
permissions_to_assign.append(PermissionToAssign(permission="read", target_uri="/data-stores/*"))
|
||||||
return permissions_to_assign
|
return permissions_to_assign
|
||||||
@ -614,6 +626,8 @@ class AuthorizationService:
|
|||||||
* Basic access to complete tasks and use the site
|
* Basic access to complete tasks and use the site
|
||||||
ELEVATED
|
ELEVATED
|
||||||
* Operations that require elevated permissions
|
* Operations that require elevated permissions
|
||||||
|
SUPPORT
|
||||||
|
* Like elevated minus access to secrets
|
||||||
|
|
||||||
Permission Macros:
|
Permission Macros:
|
||||||
all
|
all
|
||||||
@ -638,6 +652,8 @@ class AuthorizationService:
|
|||||||
permissions_to_assign += cls.set_basic_permissions()
|
permissions_to_assign += cls.set_basic_permissions()
|
||||||
elif target.startswith("ELEVATED"):
|
elif target.startswith("ELEVATED"):
|
||||||
permissions_to_assign += cls.set_elevated_permissions()
|
permissions_to_assign += cls.set_elevated_permissions()
|
||||||
|
elif target.startswith("SUPPORT"):
|
||||||
|
permissions_to_assign += cls.set_support_permissions()
|
||||||
elif target == "ALL":
|
elif target == "ALL":
|
||||||
for permission in permissions:
|
for permission in permissions:
|
||||||
permissions_to_assign.append(PermissionToAssign(permission=permission, target_uri="/*"))
|
permissions_to_assign.append(PermissionToAssign(permission=permission, target_uri="/*"))
|
||||||
|
@ -275,77 +275,29 @@ class TestAuthorizationService(BaseTest):
|
|||||||
client: FlaskClient,
|
client: FlaskClient,
|
||||||
with_db_and_bpmn_file_cleanup: None,
|
with_db_and_bpmn_file_cleanup: None,
|
||||||
) -> None:
|
) -> None:
|
||||||
expected_permissions = sorted(
|
expected_permissions = self._expected_basic_permissions()
|
||||||
[
|
|
||||||
("/active-users/*", "create"),
|
|
||||||
("/connector-proxy/typeahead/*", "read"),
|
|
||||||
("/debug/version-info", "read"),
|
|
||||||
("/extensions", "read"),
|
|
||||||
("/onboarding", "read"),
|
|
||||||
("/process-groups", "read"),
|
|
||||||
("/process-instances/find-by-id/*", "read"),
|
|
||||||
("/process-instances/for-me", "create"),
|
|
||||||
("/process-instances/report-metadata", "read"),
|
|
||||||
("/process-instances/reports/*", "create"),
|
|
||||||
("/process-instances/reports/*", "delete"),
|
|
||||||
("/process-instances/reports/*", "read"),
|
|
||||||
("/process-instances/reports/*", "update"),
|
|
||||||
("/process-models", "read"),
|
|
||||||
("/processes", "read"),
|
|
||||||
("/processes/callers/*", "read"),
|
|
||||||
("/service-tasks", "read"),
|
|
||||||
("/tasks/*", "create"),
|
|
||||||
("/tasks/*", "delete"),
|
|
||||||
("/tasks/*", "read"),
|
|
||||||
("/tasks/*", "update"),
|
|
||||||
("/user-groups/for-current-user", "read"),
|
|
||||||
("/users/exists/by-username", "create"),
|
|
||||||
("/users/search", "read"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
permissions_to_assign = AuthorizationService.explode_permissions("all", "BASIC")
|
permissions_to_assign = AuthorizationService.explode_permissions("all", "BASIC")
|
||||||
permissions_to_assign_tuples = sorted([(p.target_uri, p.permission) for p in permissions_to_assign])
|
permissions_to_assign_tuples = sorted([(p.target_uri, p.permission) for p in permissions_to_assign])
|
||||||
assert permissions_to_assign_tuples == expected_permissions
|
assert permissions_to_assign_tuples == expected_permissions
|
||||||
|
|
||||||
|
def test_explode_permissions_support(
|
||||||
|
self,
|
||||||
|
app: Flask,
|
||||||
|
client: FlaskClient,
|
||||||
|
with_db_and_bpmn_file_cleanup: None,
|
||||||
|
) -> None:
|
||||||
|
expected_permissions = self._expected_support_permissions()
|
||||||
|
permissions_to_assign = AuthorizationService.explode_permissions("all", "SUPPORT")
|
||||||
|
permissions_to_assign_tuples = sorted([(p.target_uri, p.permission) for p in permissions_to_assign])
|
||||||
|
assert permissions_to_assign_tuples == expected_permissions
|
||||||
|
|
||||||
def test_explode_permissions_elevated(
|
def test_explode_permissions_elevated(
|
||||||
self,
|
self,
|
||||||
app: Flask,
|
app: Flask,
|
||||||
client: FlaskClient,
|
client: FlaskClient,
|
||||||
with_db_and_bpmn_file_cleanup: None,
|
with_db_and_bpmn_file_cleanup: None,
|
||||||
) -> None:
|
) -> None:
|
||||||
expected_permissions = sorted(
|
expected_permissions = self._expected_elevated_permissions()
|
||||||
[
|
|
||||||
("/authentications", "read"),
|
|
||||||
("/can-run-privileged-script/*", "create"),
|
|
||||||
("/data-stores/*", "read"),
|
|
||||||
("/debug/*", "create"),
|
|
||||||
("/event-error-details/*", "read"),
|
|
||||||
("/extensions-get-data/*", "read"),
|
|
||||||
("/extensions/*", "create"),
|
|
||||||
("/logs/*", "read"),
|
|
||||||
("/messages", "read"),
|
|
||||||
("/messages/*", "create"),
|
|
||||||
("/process-data-file-download/*", "read"),
|
|
||||||
("/process-data/*", "read"),
|
|
||||||
("/process-instance-reset/*", "create"),
|
|
||||||
("/process-instance-resume/*", "create"),
|
|
||||||
("/process-instance-suspend/*", "create"),
|
|
||||||
("/process-instance-terminate/*", "create"),
|
|
||||||
("/process-instances/*", "create"),
|
|
||||||
("/process-instances/*", "delete"),
|
|
||||||
("/process-instances/*", "read"),
|
|
||||||
("/process-instances/*", "update"),
|
|
||||||
("/secrets/*", "create"),
|
|
||||||
("/secrets/*", "delete"),
|
|
||||||
("/secrets/*", "read"),
|
|
||||||
("/secrets/*", "update"),
|
|
||||||
("/send-event/*", "create"),
|
|
||||||
("/task-assign/*", "create"),
|
|
||||||
("/task-complete/*", "create"),
|
|
||||||
("/task-data/*", "update"),
|
|
||||||
("/task-data/*", "read"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
permissions_to_assign = AuthorizationService.explode_permissions("all", "ELEVATED")
|
permissions_to_assign = AuthorizationService.explode_permissions("all", "ELEVATED")
|
||||||
permissions_to_assign_tuples = sorted([(p.target_uri, p.permission) for p in permissions_to_assign])
|
permissions_to_assign_tuples = sorted([(p.target_uri, p.permission) for p in permissions_to_assign])
|
||||||
assert permissions_to_assign_tuples == expected_permissions
|
assert permissions_to_assign_tuples == expected_permissions
|
||||||
@ -489,3 +441,76 @@ class TestAuthorizationService(BaseTest):
|
|||||||
self.assert_user_has_permission(user_two, "read", "/v1.0/process-groups/hey2")
|
self.assert_user_has_permission(user_two, "read", "/v1.0/process-groups/hey2")
|
||||||
self.assert_user_has_permission(user_two, "read", "/v1.0/process-groups/hey2:yo")
|
self.assert_user_has_permission(user_two, "read", "/v1.0/process-groups/hey2:yo")
|
||||||
self.assert_user_has_permission(user_two, "create", "/v1.0/process-groups/hey2:yo")
|
self.assert_user_has_permission(user_two, "create", "/v1.0/process-groups/hey2:yo")
|
||||||
|
|
||||||
|
def _expected_basic_permissions(self) -> list[tuple[str, str]]:
|
||||||
|
return sorted(
|
||||||
|
[
|
||||||
|
("/active-users/*", "create"),
|
||||||
|
("/connector-proxy/typeahead/*", "read"),
|
||||||
|
("/debug/version-info", "read"),
|
||||||
|
("/extensions", "read"),
|
||||||
|
("/onboarding", "read"),
|
||||||
|
("/process-groups", "read"),
|
||||||
|
("/process-instances/find-by-id/*", "read"),
|
||||||
|
("/process-instances/for-me", "create"),
|
||||||
|
("/process-instances/report-metadata", "read"),
|
||||||
|
("/process-instances/reports/*", "create"),
|
||||||
|
("/process-instances/reports/*", "delete"),
|
||||||
|
("/process-instances/reports/*", "read"),
|
||||||
|
("/process-instances/reports/*", "update"),
|
||||||
|
("/process-models", "read"),
|
||||||
|
("/processes", "read"),
|
||||||
|
("/processes/callers/*", "read"),
|
||||||
|
("/service-tasks", "read"),
|
||||||
|
("/tasks/*", "create"),
|
||||||
|
("/tasks/*", "delete"),
|
||||||
|
("/tasks/*", "read"),
|
||||||
|
("/tasks/*", "update"),
|
||||||
|
("/user-groups/for-current-user", "read"),
|
||||||
|
("/users/exists/by-username", "create"),
|
||||||
|
("/users/search", "read"),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
def _expected_support_permissions(self) -> list[tuple[str, str]]:
|
||||||
|
return sorted(
|
||||||
|
self._expected_basic_permissions()
|
||||||
|
+ [
|
||||||
|
("/authentications", "read"),
|
||||||
|
("/can-run-privileged-script/*", "create"),
|
||||||
|
("/data-stores/*", "read"),
|
||||||
|
("/debug/*", "create"),
|
||||||
|
("/event-error-details/*", "read"),
|
||||||
|
("/extensions-get-data/*", "read"),
|
||||||
|
("/extensions/*", "create"),
|
||||||
|
("/logs/*", "read"),
|
||||||
|
("/messages", "read"),
|
||||||
|
("/messages/*", "create"),
|
||||||
|
("/process-data-file-download/*", "read"),
|
||||||
|
("/process-data/*", "read"),
|
||||||
|
("/process-instance-reset/*", "create"),
|
||||||
|
("/process-instance-resume/*", "create"),
|
||||||
|
("/process-instance-suspend/*", "create"),
|
||||||
|
("/process-instance-terminate/*", "create"),
|
||||||
|
("/process-instances/*", "create"),
|
||||||
|
("/process-instances/*", "delete"),
|
||||||
|
("/process-instances/*", "read"),
|
||||||
|
("/process-instances/*", "update"),
|
||||||
|
("/send-event/*", "create"),
|
||||||
|
("/task-assign/*", "create"),
|
||||||
|
("/task-complete/*", "create"),
|
||||||
|
("/task-data/*", "update"),
|
||||||
|
("/task-data/*", "read"),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
def _expected_elevated_permissions(self) -> list[tuple[str, str]]:
|
||||||
|
return sorted(
|
||||||
|
self._expected_support_permissions()
|
||||||
|
+ [
|
||||||
|
("/secrets/*", "create"),
|
||||||
|
("/secrets/*", "delete"),
|
||||||
|
("/secrets/*", "read"),
|
||||||
|
("/secrets/*", "update"),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user