def filter_grantable_permissions(session, grants, all_permissions=None): """For a given set of PERMISSION_GRANT permissions, return all permissions that are grantable. Args: session (sqlalchemy.orm.session.Session); database session grants ([Permission, ...]): PERMISSION_GRANT permissions all_permissions ({name: Permission}): all permissions to check against Returns: list of (Permission, argument) that is grantable by list of grants sorted by permission name and argument. """ if all_permissions is None: all_permissions = {permission.name: permission for permission in Permission.get_all(session)} result = [] for grant in grants: assert grant.name == PERMISSION_GRANT grantable = grant.argument.split('/', 1) if not grantable: continue for name, permission_obj in all_permissions.iteritems(): if matches_glob(grantable[0], name): result.append((permission_obj, grantable[1] if len(grantable) > 1 else '*', )) return sorted(result, key=lambda x: x[0].name + x[1])
def test_permission_grant_to_owners(session, standard_graph, groups, grantable_permissions): """Test we're getting correct owners according to granted 'grouper.permission.grant' permissions.""" perm_grant, _, perm1, perm2 = grantable_permissions assert not get_owners_by_grantable_permission(session), 'nothing to begin with' # grant a grant on a non-existent permission grant_permission(groups["auditors"], perm_grant, argument="notgrantable.one") assert not get_owners_by_grantable_permission(session), 'ignore grants for non-existent perms' # grant a wildcard grant -- make sure all permissions are represented and # the grant isn't inherited grant_permission(groups["all-teams"], perm_grant, argument="grantable.*") owners_by_arg_by_perm = get_owners_by_grantable_permission(session) expected = [groups['all-teams']] assert owners_by_arg_by_perm[perm1.name]['*'] == expected, 'grants are not inherited' assert len(owners_by_arg_by_perm) == 2 assert len(owners_by_arg_by_perm[perm1.name]) == 1 assert len(owners_by_arg_by_perm[perm2.name]) == 1 # grant on argument substring grant_permission(groups["team-sre"], perm_grant, argument="{}/somesubstring*".format( perm1.name)) owners_by_arg_by_perm = get_owners_by_grantable_permission(session) expected = [groups['all-teams']] assert owners_by_arg_by_perm[perm1.name]['*'] == expected expected = [groups["team-sre"]] assert owners_by_arg_by_perm[perm1.name]['somesubstring*'] == expected # make sure get_owner() respect substrings res = [o for o, a in get_owner_arg_list(session, perm1, "somesubstring", owners_by_arg_by_perm=owners_by_arg_by_perm)] assert (sorted(res) == sorted([groups["all-teams"], groups["team-sre"]]), "should include substring wildcard matches") res = [o for o, a in get_owner_arg_list(session, perm1, "othersubstring", owners_by_arg_by_perm=owners_by_arg_by_perm)] assert sorted(res) == [groups["all-teams"]], "negative test of substring wildcard matches" # permission admins have all the power perm_admin, _ = Permission.get_or_create(session, name=PERMISSION_ADMIN, description="") session.commit() grant_permission(groups["security-team"], perm_admin) owners_by_arg_by_perm = get_owners_by_grantable_permission(session) all_permissions = Permission.get_all(session) for perm in all_permissions: assert perm.name in owners_by_arg_by_perm, 'all permission should be represented' assert groups["security-team"] in owners_by_arg_by_perm[perm.name]["*"], \ 'permission admin should be wildcard owners'
def get_owners_by_grantable_permission(session): """ Returns all known permission arguments with owners. This consolidates permission grants supported by grouper itself as well as any grants governed by plugins. Args: session(sqlalchemy.orm.session.Session): database session Returns: A map of permission to argument to owners of the form {permission: {argument: [owner1, ...], }, } where 'owners' are models.Group objects. And 'argument' can be '*' which means 'anything'. """ all_permissions = {permission.name: permission for permission in Permission.get_all(session)} all_groups = session.query(Group).filter(Group.enabled == True).all() owners_by_arg_by_perm = defaultdict(lambda: defaultdict(list)) for group in all_groups: group_permissions = session.query( Permission.name, PermissionMap.argument, PermissionMap.granted_on, Group, ).filter( PermissionMap.group_id == Group.id, Group.id == group.id, Permission.id == PermissionMap.permission_id, ).all() # special case permission admins if any(filter(lambda g: g.name == PERMISSION_ADMIN, group_permissions)): for perm_name in all_permissions: owners_by_arg_by_perm[perm_name]["*"].append(group) continue grants = [gp for gp in group_permissions if gp.name == PERMISSION_GRANT] for perm, arg in filter_grantable_permissions(session, grants, all_permissions=all_permissions): owners_by_arg_by_perm[perm.name][arg].append(group) # merge in plugin results for plugin in get_plugins(): res = plugin.get_owner_by_arg_by_perm(session) or {} for perm, owners_by_arg in res.items(): for arg, owners in owners_by_arg.items(): owners_by_arg_by_perm[perm][arg] += owners return owners_by_arg_by_perm