Esempio n. 1
0
def user_grantable_permissions(session, user):
    '''
    Returns a list of permissions this user is allowed to grant. Presently, this only counts
    permissions that a user has directly -- in other words, the 'grant' permissions are not
    counted as inheritable.

    TODO: consider making these permissions inherited? This requires walking the graph, which
    is expensive.

    Returns a list of tuples (Permission, argument) that the user is allowed to grant.
    '''
    # avoid circular dependency
    from grouper.permissions import filter_grantable_permissions

    all_permissions = {
        permission.name: permission
        for permission in Permission.get_all(session)
    }
    if user_is_permission_admin(session, user):
        result = [(perm, '*') for perm in all_permissions.values()]
        return sorted(result, key=lambda x: x[0].name + x[1])

    # Someone can grant a permission if they are a member of a group that has a permission
    # of PERMISSION_GRANT with an argument that matches the name of a permission.
    grants = [
        x for x in user_permissions(session, user)
        if x.name == PERMISSION_GRANT
    ]
    return filter_grantable_permissions(session, grants)
Esempio n. 2
0
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])
Esempio n. 3
0
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])
Esempio n. 4
0
def get_owners_by_grantable_permission(session, separate_global=False):
    """
    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))

    all_group_permissions = session.query(
            Permission.name,
            PermissionMap.argument,
            PermissionMap.granted_on,
            Group,
    ).filter(
            PermissionMap.group_id == Group.id,
            Permission.id == PermissionMap.permission_id,
    ).all()

    grants_by_group = defaultdict(list)

    for grant in all_group_permissions:
        grants_by_group[grant.Group.id].append(grant)

    for group in all_groups:
        # special case permission admins
        group_permissions = grants_by_group[group.id]
        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)
            if separate_global:
                owners_by_arg_by_perm[GLOBAL_OWNERS]["*"].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
Esempio n. 5
0
def get_owners_by_grantable_permission(session, separate_global=False):
    """
    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))

    all_group_permissions = session.query(
            Permission.name,
            PermissionMap.argument,
            PermissionMap.granted_on,
            Group,
    ).filter(
            PermissionMap.group_id == Group.id,
            Permission.id == PermissionMap.permission_id,
    ).all()

    grants_by_group = defaultdict(list)

    for grant in all_group_permissions:
        grants_by_group[grant.Group.id].append(grant)

    for group in all_groups:
        # special case permission admins
        group_permissions = grants_by_group[group.id]
        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)
            if separate_global:
                owners_by_arg_by_perm[GLOBAL_OWNERS]["*"].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 res in get_plugin_proxy().get_owner_by_arg_by_perm(session):
        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
Esempio n. 6
0
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"
Esempio n. 7
0
def user_grantable_permissions(session, user):
    '''
    Returns a list of permissions this user is allowed to grant. Presently, this only counts
    permissions that a user has directly -- in other words, the 'grant' permissions are not
    counted as inheritable.

    TODO: consider making these permissions inherited? This requires walking the graph, which
    is expensive.

    Returns a list of tuples (Permission, argument) that the user is allowed to grant.
    '''
    # avoid circular dependency
    from grouper.permissions import filter_grantable_permissions

    all_permissions = {permission.name: permission
                       for permission in Permission.get_all(session)}
    if user_is_permission_admin(session, user):
        result = [(perm, '*') for perm in all_permissions.values()]
        return sorted(result, key=lambda x: x[0].name + x[1])

    # Someone can grant a permission if they are a member of a group that has a permission
    # of PERMISSION_GRANT with an argument that matches the name of a permission.
    grants = [x for x in user_permissions(session, user) if x.name == PERMISSION_GRANT]
    return filter_grantable_permissions(session, grants)
Esempio n. 8
0
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'