##// END OF EJS Templates
fix(permissions): fixed security problem with apply-to-children functionality breaking permissions for private repositories...
super-admin -
r5550:cb083474 default
parent child Browse files
Show More
@@ -1,4 +1,4 b''
1 # Copyright (C) 2011-2023 RhodeCode GmbH
1 # Copyright (C) 2011-2024 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -30,7 +30,6 b' import time'
30 import traceback
30 import traceback
31 import string
31 import string
32
32
33 from zope.cachedescriptors.property import Lazy as LazyProperty
34
33
35 from rhodecode import events
34 from rhodecode import events
36 from rhodecode.model import BaseModel
35 from rhodecode.model import BaseModel
@@ -38,7 +37,7 b' from rhodecode.model.db import (_hash_ke'
38 Session, RepoGroup, UserRepoGroupToPerm, User, Permission, UserGroupRepoGroupToPerm,
37 Session, RepoGroup, UserRepoGroupToPerm, User, Permission, UserGroupRepoGroupToPerm,
39 UserGroup, Repository)
38 UserGroup, Repository)
40 from rhodecode.model.permission import PermissionModel
39 from rhodecode.model.permission import PermissionModel
41 from rhodecode.model.settings import VcsSettingsModel, SettingsModel
40 from rhodecode.model.settings import SettingsModel
42 from rhodecode.lib.caching_query import FromCache
41 from rhodecode.lib.caching_query import FromCache
43 from rhodecode.lib.utils2 import action_logger_generic
42 from rhodecode.lib.utils2 import action_logger_generic
44
43
@@ -350,46 +349,45 b' class RepoGroupModel(BaseModel):'
350 'default_user_changed': None
349 'default_user_changed': None
351 }
350 }
352
351
353 def _set_perm_user(obj, user, perm):
352 def _set_perm_user(_obj: RepoGroup | Repository, _user_obj: User, _perm):
354 if isinstance(obj, RepoGroup):
353
355 self.grant_user_permission(
354 if isinstance(_obj, RepoGroup):
356 repo_group=obj, user=user, perm=perm)
355 self.grant_user_permission(repo_group=_obj, user=_user_obj, perm=_perm)
357 elif isinstance(obj, Repository):
356 elif isinstance(_obj, Repository):
358 # private repos will not allow to change the default
357 # private repos will not allow to change the default
359 # permissions using recursive mode
358 # permissions using recursive mode
360 if obj.private and user == User.DEFAULT_USER:
359 if _obj.private and _user_obj.username == User.DEFAULT_USER:
360 log.debug('Skipping private repo %s for user %s', _obj, _user_obj)
361 return
361 return
362
362
363 # we set group permission but we have to switch to repo
363 # we set group permission, we have to switch to repo permission definition
364 # permission
364 new_perm = _perm.replace('group.', 'repository.')
365 perm = perm.replace('group.', 'repository.')
365 RepoModel().grant_user_permission(repo=_obj, user=_user_obj, perm=new_perm)
366 RepoModel().grant_user_permission(
366
367 repo=obj, user=user, perm=perm)
367 def _set_perm_group(_obj: RepoGroup | Repository, users_group: UserGroup, _perm):
368 if isinstance(_obj, RepoGroup):
369 self.grant_user_group_permission(repo_group=_obj, group_name=users_group, perm=_perm)
370 elif isinstance(_obj, Repository):
371 # we set group permission, we have to switch to repo permission definition
372 new_perm = _perm.replace('group.', 'repository.')
373 RepoModel().grant_user_group_permission(repo=_obj, group_name=users_group, perm=new_perm)
368
374
369 def _set_perm_group(obj, users_group, perm):
375 def _revoke_perm_user(_obj: RepoGroup | Repository, _user_obj: User):
370 if isinstance(obj, RepoGroup):
376 if isinstance(_obj, RepoGroup):
371 self.grant_user_group_permission(
377 self.revoke_user_permission(repo_group=_obj, user=_user_obj)
372 repo_group=obj, group_name=users_group, perm=perm)
378 elif isinstance(_obj, Repository):
373 elif isinstance(obj, Repository):
379 # private repos will not allow to change the default
374 # we set group permission but we have to switch to repo
380 # permissions using recursive mode, also there's no revocation fo default user, just update
375 # permission
381 if _user_obj.username == User.DEFAULT_USER:
376 perm = perm.replace('group.', 'repository.')
382 log.debug('Skipping private repo %s for user %s', _obj, _user_obj)
377 RepoModel().grant_user_group_permission(
383 return
378 repo=obj, group_name=users_group, perm=perm)
384 RepoModel().revoke_user_permission(repo=_obj, user=_user_obj)
379
385
380 def _revoke_perm_user(obj, user):
386 def _revoke_perm_group(_obj: RepoGroup | Repository, user_group: UserGroup):
381 if isinstance(obj, RepoGroup):
387 if isinstance(_obj, RepoGroup):
382 self.revoke_user_permission(repo_group=obj, user=user)
388 self.revoke_user_group_permission(repo_group=_obj, group_name=user_group)
383 elif isinstance(obj, Repository):
389 elif isinstance(_obj, Repository):
384 RepoModel().revoke_user_permission(repo=obj, user=user)
390 RepoModel().revoke_user_group_permission(repo=_obj, group_name=user_group)
385
386 def _revoke_perm_group(obj, user_group):
387 if isinstance(obj, RepoGroup):
388 self.revoke_user_group_permission(
389 repo_group=obj, group_name=user_group)
390 elif isinstance(obj, Repository):
391 RepoModel().revoke_user_group_permission(
392 repo=obj, group_name=user_group)
393
391
394 # start updates
392 # start updates
395 log.debug('Now updating permissions for %s in recursive mode:%s',
393 log.debug('Now updating permissions for %s in recursive mode:%s',
@@ -423,7 +421,8 b' class RepoGroupModel(BaseModel):'
423 for member_id, perm, member_type in perm_updates:
421 for member_id, perm, member_type in perm_updates:
424 member_id = int(member_id)
422 member_id = int(member_id)
425 if member_type == 'user':
423 if member_type == 'user':
426 member_name = User.get(member_id).username
424 member_obj = User.get(member_id)
425 member_name = member_obj.username
427 if isinstance(obj, RepoGroup) and obj == repo_group and member_name == User.DEFAULT_USER:
426 if isinstance(obj, RepoGroup) and obj == repo_group and member_name == User.DEFAULT_USER:
428 # NOTE(dan): detect if we changed permissions for default user
427 # NOTE(dan): detect if we changed permissions for default user
429 perm_obj = self.sa.query(UserRepoGroupToPerm) \
428 perm_obj = self.sa.query(UserRepoGroupToPerm) \
@@ -434,15 +433,16 b' class RepoGroupModel(BaseModel):'
434 changes['default_user_changed'] = True
433 changes['default_user_changed'] = True
435
434
436 # this updates also current one if found
435 # this updates also current one if found
437 _set_perm_user(obj, user=member_id, perm=perm)
436 _set_perm_user(obj, member_obj, perm)
438 elif member_type == 'user_group':
437 elif member_type == 'user_group':
439 member_name = UserGroup.get(member_id).users_group_name
438 member_obj = UserGroup.get(member_id)
440 if not check_perms or has_group_perm(member_name,
439 member_name = member_obj.users_group_name
441 user=cur_user):
440 if not check_perms or has_group_perm(member_name, user=cur_user):
442 _set_perm_group(obj, users_group=member_id, perm=perm)
441 _set_perm_group(obj, member_obj, perm)
443 else:
442 else:
444 raise ValueError("member_type must be 'user' or 'user_group' "
443 raise ValueError(
445 "got {} instead".format(member_type))
444 f"member_type must be 'user' or 'user_group' got {member_type} instead"
445 )
446
446
447 changes['updated'].append(
447 changes['updated'].append(
448 {'change_obj': change_obj, 'type': member_type,
448 {'change_obj': change_obj, 'type': member_type,
@@ -452,17 +452,19 b' class RepoGroupModel(BaseModel):'
452 for member_id, perm, member_type in perm_additions:
452 for member_id, perm, member_type in perm_additions:
453 member_id = int(member_id)
453 member_id = int(member_id)
454 if member_type == 'user':
454 if member_type == 'user':
455 member_name = User.get(member_id).username
455 member_obj = User.get(member_id)
456 _set_perm_user(obj, user=member_id, perm=perm)
456 member_name = member_obj.username
457 _set_perm_user(obj, member_obj, perm)
457 elif member_type == 'user_group':
458 elif member_type == 'user_group':
458 # check if we have permissions to alter this usergroup
459 # check if we have permissions to alter this usergroup
459 member_name = UserGroup.get(member_id).users_group_name
460 member_obj = UserGroup.get(member_id)
460 if not check_perms or has_group_perm(member_name,
461 member_name = member_obj.users_group_name
461 user=cur_user):
462 if not check_perms or has_group_perm(member_name, user=cur_user):
462 _set_perm_group(obj, users_group=member_id, perm=perm)
463 _set_perm_group(obj, member_obj, perm)
463 else:
464 else:
464 raise ValueError("member_type must be 'user' or 'user_group' "
465 raise ValueError(
465 "got {} instead".format(member_type))
466 f"member_type must be 'user' or 'user_group' got {member_type} instead"
467 )
466
468
467 changes['added'].append(
469 changes['added'].append(
468 {'change_obj': change_obj, 'type': member_type,
470 {'change_obj': change_obj, 'type': member_type,
@@ -472,18 +474,19 b' class RepoGroupModel(BaseModel):'
472 for member_id, perm, member_type in perm_deletions:
474 for member_id, perm, member_type in perm_deletions:
473 member_id = int(member_id)
475 member_id = int(member_id)
474 if member_type == 'user':
476 if member_type == 'user':
475 member_name = User.get(member_id).username
477 member_obj = User.get(member_id)
476 _revoke_perm_user(obj, user=member_id)
478 member_name = member_obj.username
479 _revoke_perm_user(obj, member_obj)
477 elif member_type == 'user_group':
480 elif member_type == 'user_group':
478 # check if we have permissions to alter this usergroup
481 # check if we have permissions to alter this usergroup
479 member_name = UserGroup.get(member_id).users_group_name
482 member_obj = UserGroup.get(member_id)
480 if not check_perms or has_group_perm(member_name,
483 member_name = member_obj.users_group_name
481 user=cur_user):
484 if not check_perms or has_group_perm(member_name, user=cur_user):
482 _revoke_perm_group(obj, user_group=member_id)
485 _revoke_perm_group(obj, member_obj)
483 else:
486 else:
484 raise ValueError("member_type must be 'user' or 'user_group' "
487 raise ValueError(
485 "got {} instead".format(member_type))
488 f"member_type must be 'user' or 'user_group' got {member_type} instead"
486
489 )
487 changes['deleted'].append(
490 changes['deleted'].append(
488 {'change_obj': change_obj, 'type': member_type,
491 {'change_obj': change_obj, 'type': member_type,
489 'id': member_id, 'name': member_name, 'new_perm': perm})
492 'id': member_id, 'name': member_name, 'new_perm': perm})
General Comments 0
You need to be logged in to leave comments. Login now