diff --git a/src/middlewared/middlewared/plugins/account_/privilege.py b/src/middlewared/middlewared/plugins/account_/privilege.py index c50549cf95e0c..c87094994b070 100644 --- a/src/middlewared/middlewared/plugins/account_/privilege.py +++ b/src/middlewared/middlewared/plugins/account_/privilege.py @@ -4,7 +4,11 @@ from middlewared.schema import accepts, Bool, Dict, Int, List, Ref, SID, Str, Patch from middlewared.service import CallError, CRUDService, filter_list, private, ValidationErrors from middlewared.service_exception import MatchNotFound -from middlewared.utils.privilege import privilege_has_webui_access, privileges_group_mapping +from middlewared.utils.privilege import ( + LocalAdminGroups, + privilege_has_webui_access, + privileges_group_mapping +) import middlewared.sqlalchemy as sa @@ -125,6 +129,13 @@ async def do_update(self, id_, data): builtin_privilege = BuiltinPrivileges(new["builtin_name"]) if builtin_privilege == BuiltinPrivileges.LOCAL_ADMINISTRATOR: + if LocalAdminGroups.BUILTIN_ADMINISTRATORS not in new["local_groups"]: + verrors.add( + "privilege_update.local_groups", + f"The group {LocalAdminGroups.BUILTIN_ADMINISTRATORS.name.lower()} must be " + "among grantees of the \"Local Administrator\" privilege." + ) + if not await self.middleware.call("group.has_password_enabled_user", new["local_groups"]): verrors.add( "privilege_update.local_groups", diff --git a/src/middlewared/middlewared/utils/privilege.py b/src/middlewared/middlewared/utils/privilege.py index 5c243403b5ca4..f2de7b6e55088 100644 --- a/src/middlewared/middlewared/utils/privilege.py +++ b/src/middlewared/middlewared/utils/privilege.py @@ -1,6 +1,11 @@ +import enum from middlewared.role import ROLES +class LocalAdminGroups(enum.IntEnum): + BUILTIN_ADMINISTRATORS = 544 + + def privilege_has_webui_access(privilege: dict) -> bool: """ This method determines whether the specified privilege is sufficient