fix: enforce strict RBAC - deny access for users without groups

Security fix: Previously users with no OAuth groups or unrecognized
groups would default to READ_ONLY access. Now:
- Empty groups = no permissions (denied access to all tools)
- Unrecognized groups = no permissions (denied access)

Also adds missing restart_service mapping to FULL_ADMIN permission.
This commit is contained in:
Ryan Malloy 2025-12-27 08:10:01 -07:00
parent 6159098963
commit 00857b1840

View File

@ -120,10 +120,11 @@ TOOL_PERMISSIONS: dict[str, PermissionLevel] = {
"configure_ntp": PermissionLevel.HOST_ADMIN, "configure_ntp": PermissionLevel.HOST_ADMIN,
"set_service_policy": PermissionLevel.HOST_ADMIN, "set_service_policy": PermissionLevel.HOST_ADMIN,
# ═══════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════
# FULL_ADMIN - Everything including guest OS and service control (10 tools) # FULL_ADMIN - Everything including guest OS and service control (11 tools)
# ═══════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════
"start_service": PermissionLevel.FULL_ADMIN, "start_service": PermissionLevel.FULL_ADMIN,
"stop_service": PermissionLevel.FULL_ADMIN, "stop_service": PermissionLevel.FULL_ADMIN,
"restart_service": PermissionLevel.FULL_ADMIN,
# Guest OS operations (requires guest credentials, high privilege) # Guest OS operations (requires guest credentials, high privilege)
"run_command_in_guest": PermissionLevel.FULL_ADMIN, "run_command_in_guest": PermissionLevel.FULL_ADMIN,
"list_guest_processes": PermissionLevel.FULL_ADMIN, "list_guest_processes": PermissionLevel.FULL_ADMIN,
@ -191,9 +192,10 @@ def get_user_permissions(groups: list[str] | None) -> set[PermissionLevel]:
Returns: Returns:
Set of granted permission levels (union of all group permissions). Set of granted permission levels (union of all group permissions).
Returns empty set if no recognized groups (deny all access).
""" """
if not groups: if not groups:
return {PermissionLevel.READ_ONLY} return set() # No groups = no permissions (enforces RBAC)
permissions: set[PermissionLevel] = set() permissions: set[PermissionLevel] = set()
@ -201,10 +203,7 @@ def get_user_permissions(groups: list[str] | None) -> set[PermissionLevel]:
if group in GROUP_PERMISSIONS: if group in GROUP_PERMISSIONS:
permissions.update(GROUP_PERMISSIONS[group]) permissions.update(GROUP_PERMISSIONS[group])
# Default to read-only if no recognized groups # No fallback - unrecognized groups get no permissions
if not permissions:
permissions.add(PermissionLevel.READ_ONLY)
return permissions return permissions