Пример #1
0
def test_permission_grants_for_group(setup):
    # type: (SetupTest) -> None
    with setup.transaction():
        setup.grant_permission_to_group("some-permission", "one", "some-group")
        setup.grant_permission_to_group("some-permission", "two", "some-group")
        setup.grant_permission_to_group("other-permission", "*", "some-group")
        setup.grant_permission_to_group("parent-permission", "foo",
                                        "parent-group")
        setup.add_group_to_group("some-group", "parent-group")
        setup.create_group("other-group")
        setup.create_user("*****@*****.**")

    mock_ui = MagicMock()
    usecase = setup.usecase_factory.create_grant_permission_to_service_account_usecase(
        "*****@*****.**", mock_ui)
    expected = [
        GroupPermissionGrant(
            group="some-group",
            permission="other-permission",
            argument="*",
            granted_on=ANY,
            is_alias=False,
            grant_id=ANY,
        ),
        GroupPermissionGrant(
            group="some-group",
            permission="parent-permission",
            argument="foo",
            granted_on=ANY,
            is_alias=False,
            grant_id=ANY,
        ),
        GroupPermissionGrant(
            group="some-group",
            permission="some-permission",
            argument="one",
            granted_on=ANY,
            is_alias=False,
            grant_id=ANY,
        ),
        GroupPermissionGrant(
            group="some-group",
            permission="some-permission",
            argument="two",
            granted_on=ANY,
            is_alias=False,
            grant_id=ANY,
        ),
    ]
    assert sorted(
        usecase.permission_grants_for_group("some-group")) == expected
    assert usecase.permission_grants_for_group("other-group") == []
Пример #2
0
    def group_grants_for_permission(self,
                                    name,
                                    include_disabled_groups=False,
                                    argument=None):
        # type: (str, bool, Optional[str]) -> List[GroupPermissionGrant]
        permission = Permission.get(self.session, name=name)
        if not permission or not permission.enabled:
            return []
        grants = (self.session.query(
            Group.groupname, PermissionMap.argument, PermissionMap.id,
            PermissionMap.granted_on).filter(
                PermissionMap.permission_id == permission.id,
                Group.id == PermissionMap.group_id).order_by(
                    Group.groupname, PermissionMap.argument))
        if not include_disabled_groups:
            grants = grants.filter(Group.enabled == True)

        if argument:
            grants = grants.filter(PermissionMap.argument == argument)

        return [
            GroupPermissionGrant(
                group=g.groupname,
                permission=name,
                argument=g.argument,
                granted_on=g.granted_on,
                is_alias=False,
                grant_id=g.id,
            ) for g in grants.all()
        ]
Пример #3
0
def test_permission_disable_existing_grants(setup):
    # type: (SetupTest) -> None
    with setup.transaction():
        setup.grant_permission_to_group(PERMISSION_ADMIN, "", "admins")
        setup.add_user_to_group("*****@*****.**", "admins")
        setup.grant_permission_to_group("some-permission", "argument",
                                        "some-group")
        setup.create_service_account("*****@*****.**", "some-group")
        setup.grant_permission_to_service_account("some-permission", "",
                                                  "*****@*****.**")

    mock_ui = MagicMock()
    usecase = setup.usecase_factory.create_disable_permission_usecase(
        "*****@*****.**", mock_ui)
    usecase.disable_permission("some-permission")
    assert mock_ui.mock_calls == [
        call.disable_permission_failed_existing_grants(
            "some-permission",
            [
                GroupPermissionGrant("some-group", "some-permission",
                                     "argument")
            ],
            [
                ServiceAccountPermissionGrant("*****@*****.**",
                                              "some-permission", "")
            ],
        )
    ]
Пример #4
0
def test_grant_permission(tmpdir: LocalPath, setup: SetupTest,
                          browser: Chrome) -> None:
    with setup.transaction():
        setup.add_user_to_group("*****@*****.**", "some-group")
        setup.grant_permission_to_group(PERMISSION_GRANT, "some-permission",
                                        "some-group")
        setup.create_permission("some-permission")
        setup.create_group("other-group")

    with frontend_server(tmpdir, "*****@*****.**") as frontend_url:
        browser.get(url(frontend_url, "/groups/some-group"))

        group_page = GroupViewPage(browser)
        assert group_page.find_permission_rows("some-permission") == []
        group_page.click_add_permission_button()

        grant_page = PermissionGrantPage(browser)
        grant_page.set_permission("some-permission")
        grant_page.set_argument("foo")
        grant_page.submit()

        rows = group_page.find_permission_rows("some-permission")
        assert len(rows) == 1
        assert rows[0].argument == "foo"

        # Grant a permission with surrounding and internal whitespace to test whitespace handling.
        browser.get(url(frontend_url, "/groups/other-group"))
        assert group_page.find_permission_rows("some-permission") == []
        group_page.click_add_permission_button()

        grant_page.set_permission("some-permission")
        grant_page.set_argument("  arg u  ment  ")
        grant_page.submit()

        rows = group_page.find_permission_rows("some-permission")
        assert len(rows) == 1
        assert rows[0].argument in ("arg u ment", "arg u  ment"
                                    )  # browser messes with whitespace

    # Check directly in the database to make sure the whitespace is stripped, since we may not be
    # able to see it via the browser.  We need to explicitly reopen the database since otherwise
    # SQLite doesn't always see changes written by the frontend.
    setup.reopen_database()
    permission_grant_repository = setup.sql_repository_factory.create_permission_grant_repository(
    )
    grants = permission_grant_repository.permission_grants_for_group(
        "other-group")
    assert grants == [
        GroupPermissionGrant(
            group="other-group",
            permission="some-permission",
            argument="arg u  ment",
            granted_on=ANY,
            is_alias=False,
            grant_id=ANY,
        )
    ]
Пример #5
0
    def _permission_grants_for_group_ids(self, group_ids):
        # type: (Iterable[int]) -> List[GroupPermissionGrant]
        """Given a set of group IDs, return all direct or inherited permission grants.

        Used to build the full list of permission grants for a set of groups, taking inheritance
        into account.  Shared code between permission_grants_for_user and
        permission_grants_for_group.

        TODO(rra): Currently does not expand permission aliases, and therefore doesn't match the
        graph behavior.
        """
        # Get the parent groups of the initial groups, repeating until we run out of levels of the
        # tree.  Use a set of seen group_ids to avoid querying the same group twice if a user is a
        # member of it via multiple paths.
        now = datetime.utcnow()
        seen_group_ids = set(group_ids)
        while group_ids:
            parent_groups = (self.session.query(Group.id).join(
                GroupEdge, Group.id == GroupEdge.group_id).filter(
                    GroupEdge.member_pk.in_(group_ids),
                    Group.enabled == True,
                    GroupEdge.active == True,
                    GroupEdge.member_type == OBJ_TYPES["Group"],
                    GroupEdge._role != GROUP_EDGE_ROLES.index("np-owner"),
                    or_(GroupEdge.expiration > now,
                        GroupEdge.expiration == None),
                ).distinct())
            group_ids = [
                g.id for g in parent_groups if g.id not in seen_group_ids
            ]
            seen_group_ids.update(group_ids)

        # Return the permission grants.
        group_permission_grants = (self.session.query(
            Group.groupname,
            Permission.name,
            PermissionMap.argument,
            PermissionMap.granted_on,
            PermissionMap.id,
        ).filter(
            Permission.id == PermissionMap.permission_id,
            PermissionMap.group_id.in_(seen_group_ids),
            Group.id == PermissionMap.group_id,
        ).all())
        return [
            GroupPermissionGrant(
                group=g.groupname,
                permission=g.name,
                argument=g.argument,
                granted_on=g.granted_on,
                is_alias=False,
                grant_id=g.id,
            ) for g in group_permission_grants
        ]
Пример #6
0
    def _get_group_grants(session):
        # type: (Session) -> Dict[str, List[GroupPermissionGrant]]
        """Returns a dict of group names to lists of permission grants."""
        permissions = session.query(SQLPermission, PermissionMap, SQLGroup.groupname).filter(
            SQLPermission.id == PermissionMap.permission_id,
            PermissionMap.group_id == SQLGroup.id,
            SQLGroup.enabled == True,
        )

        out = defaultdict(list)  # type: Dict[str, List[GroupPermissionGrant]]
        for (permission, permission_map, groupname) in permissions:
            out[groupname].append(
                GroupPermissionGrant(
                    group=groupname,
                    permission=permission.name,
                    argument=permission_map.argument,
                    granted_on=permission_map.granted_on,
                    is_alias=False,
                    grant_id=permission_map.id,
                )
            )

            aliases = get_plugin_proxy().get_aliases_for_mapped_permission(
                session, permission.name, permission_map.argument
            )

            for (name, arg) in aliases:
                out[groupname].append(
                    GroupPermissionGrant(
                        group=groupname,
                        permission=name,
                        argument=arg,
                        granted_on=permission_map.granted_on,
                        is_alias=True,
                        grant_id=None,
                    )
                )

        return out
Пример #7
0
 def group_grants_for_permission(self, name, include_disabled_groups=False):
     # type: (str, bool) -> List[GroupPermissionGrant]
     permission = Permission.get(self.session, name=name)
     if not permission or not permission.enabled:
         return []
     grants = (
         self.session.query(Group.groupname, PermissionMap.argument)
         .filter(
             PermissionMap.permission_id == permission.id, Group.id == PermissionMap.group_id
         )
         .order_by(Group.groupname, PermissionMap.argument)
     )
     if not include_disabled_groups:
         grants = grants.filter(Group.enabled == True)
     return [GroupPermissionGrant(g.groupname, name, g.argument) for g in grants.all()]
Пример #8
0
 def permission_grants_for_user(self, name):
     # type: (str) -> List[GroupPermissionGrant]
     user_details = self.graph.get_user_details(name)
     permissions = []
     for permission_data in user_details["permissions"]:
         permission = GroupPermissionGrant(
             group=permission_data["path"][-1],
             permission=permission_data["permission"],
             argument=permission_data["argument"],
             granted_on=datetime.utcfromtimestamp(
                 permission_data["granted_on"]),
             is_alias=permission_data["alias"],
         )
         permissions.append(permission)
     return permissions
Пример #9
0
 def revoke_all_group_grants(self, permission):
     # type: (str) -> List[GroupPermissionGrant]
     sql_permission = Permission.get(self.session, name=permission)
     if not sql_permission:
         return []
     grants = (
         self.session.query(PermissionMap.id, Group.groupname, PermissionMap.argument)
         .filter(
             Group.id == PermissionMap.group_id,
             PermissionMap.permission_id == sql_permission.id,
         )
         .all()
     )
     ids = [g.id for g in grants]
     self.session.query(PermissionMap).filter(PermissionMap.id.in_(ids)).delete(
         synchronize_session="fetch"
     )
     return [GroupPermissionGrant(g.groupname, permission, g.argument) for g in grants]
Пример #10
0
def test_end_to_end_whitespace_in_argument(tmpdir, setup, browser):
    # type: (LocalPath, SetupTest, Chrome) -> None
    with setup.transaction():
        setup.create_group("some-group")
        setup.create_permission("some-permission")
        setup.add_user_to_group("*****@*****.**", "some-group", "owner")
        setup.add_user_to_group("*****@*****.**", "admins")
        setup.grant_permission_to_group(PERMISSION_GRANT, "some-permission", "admins")

    with frontend_server(tmpdir, "*****@*****.**") as frontend_url:
        browser.get(url(frontend_url, "/permissions/some-permission"))

        permission_page = PermissionPage(browser)
        assert permission_page.subheading == "some-permission"
        permission_page.button_to_request_this_permission.click()

        permission_request_page = PermissionRequestPage(browser)
        permission_request_page.set_group("some-group")
        permission_request_page.set_argument_freeform("  arg u  ment  ")
        permission_request_page.set_reason("testing whitespace")
        permission_request_page.submit()

    with frontend_server(tmpdir, "*****@*****.**") as frontend_url:
        browser.get(url(frontend_url, "/permissions/requests?status=pending"))

        requests_page = PermissionRequestsPage(browser)
        request_rows = requests_page.request_rows
        assert len(request_rows) == 1
        request = request_rows[0]
        request.click_modify_link()

        modify_page = PermissionRequestUpdatePage(browser)
        modify_page.set_status("actioned")
        modify_page.set_reason("testing whitespace")
        modify_page.submit()

        browser.get(url(frontend_url, "/groups/some-group?refresh=yes"))
        group_page = GroupViewPage(browser)
        permission_rows = group_page.find_permission_rows("some-permission")
        assert len(permission_rows) == 1
        grant = permission_rows[0]
        assert grant.name == "some-permission"
        assert grant.argument in ("arg u ment", "arg u  ment")  # browser messes with whitespace
        assert grant.source == "(direct)"

    # Check directly in the database to make sure the whitespace is stripped, since we may not be
    # able to see it via the browser.  We need to explicitly reopen the database since otherwise
    # SQLite doesn't always see changes written by the frontend.
    setup.reopen_database()
    permission_grant_repository = setup.sql_repository_factory.create_permission_grant_repository()
    grants = permission_grant_repository.permission_grants_for_group("some-group")
    assert grants == [
        GroupPermissionGrant(
            group="some-group",
            permission="some-permission",
            argument="arg u  ment",
            granted_on=ANY,
            is_alias=False,
            grant_id=ANY,
        )
    ]
Пример #11
0
    def permission_grants_for_user(self, name):
        # type: (str) -> List[GroupPermissionGrant]
        """Return all permission grants a user has from whatever source.

        TODO(rra): Currently does not expand permission aliases, and therefore doesn't match the
        graph behavior.  Use with caution until that is fixed.
        """
        now = datetime.utcnow()
        user = User.get(self.session, name=name)
        if not user or user.role_user or user.is_service_account or not user.enabled:
            return []

        # Get the groups of which this user is a direct member.
        groups = (self.session.query(Group.id).join(
            GroupEdge, Group.id == GroupEdge.group_id).join(
                User, User.id == GroupEdge.member_pk).filter(
                    Group.enabled == True,
                    User.id == user.id,
                    GroupEdge.active == True,
                    GroupEdge.member_type == OBJ_TYPES["User"],
                    GroupEdge._role != GROUP_EDGE_ROLES.index("np-owner"),
                    or_(GroupEdge.expiration > now,
                        GroupEdge.expiration == None),
                ).distinct())
        group_ids = [g.id for g in groups]

        # If the user was not a member of any group, we can return early.
        if not group_ids:
            return []

        # Now, get the parent groups of those groups and so forth until we run out of levels of the
        # tree.  Use a set of seen group_ids to avoid querying the same group twice if a user is a
        # member of it via multiple paths.
        seen_group_ids = set(group_ids)
        while group_ids:
            parent_groups = (self.session.query(Group.id).join(
                GroupEdge, Group.id == GroupEdge.group_id).filter(
                    GroupEdge.member_pk.in_(group_ids),
                    Group.enabled == True,
                    GroupEdge.active == True,
                    GroupEdge.member_type == OBJ_TYPES["Group"],
                    GroupEdge._role != GROUP_EDGE_ROLES.index("np-owner"),
                    or_(GroupEdge.expiration > now,
                        GroupEdge.expiration == None),
                ).distinct())
            group_ids = [
                g.id for g in parent_groups if g.id not in seen_group_ids
            ]
            seen_group_ids.update(group_ids)

        # Return the permission grants.
        group_permission_grants = (self.session.query(
            Group.groupname,
            Permission.name,
            PermissionMap.argument,
            PermissionMap.granted_on,
            PermissionMap.id,
        ).filter(
            Permission.id == PermissionMap.permission_id,
            PermissionMap.group_id.in_(seen_group_ids),
            Group.id == PermissionMap.group_id,
        ).all())
        return [
            GroupPermissionGrant(
                group=g.groupname,
                permission=g.name,
                argument=g.argument,
                granted_on=g.granted_on,
                is_alias=False,
                grant_id=g.id,
            ) for g in group_permission_grants
        ]