コード例 #1
0
def test_grant_permission_to_tag(users, http_client, base_url, session):  # noqa: F811

    user = session.query(User).filter_by(username="******").scalar()

    perm = create_permission(session, TAG_EDIT)
    session.commit()

    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, TAG_EDIT),
        "*",
    )

    fe_url = url(base_url, "/tags")
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"tagname": "tyler_was_here", "description": "Test Tag Please Ignore"}),
        headers={"X-Grouper-User": user.username},
    )

    tag = PublicKeyTag.get(session, name="tyler_was_here")

    user = session.query(User).filter_by(username="******").scalar()

    fe_url = url(base_url, "/permissions/grant_tag/{}".format(tag.name))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"permission": TAG_EDIT, "argument": "*"}),
        headers={"X-Grouper-User": user.username},
    )

    assert resp.code == 200
    tag = PublicKeyTag.get(session, name="tyler_was_here")
    perm = get_permission(session, TAG_EDIT)
    assert (
        len(get_public_key_tag_permissions(session, tag)) == 1
    ), "The tag should have exactly 1 permission"
    assert (
        get_public_key_tag_permissions(session, tag)[0].name == perm.name
    ), "The tag's permission should be the one we added"
    assert (
        get_public_key_tag_permissions(session, tag)[0].argument == "*"
    ), "The tag's permission should be the one we added"

    # Make sure trying to add a permission to a tag doesn't fail horribly if it's already there
    user = session.query(User).filter_by(username="******").scalar()

    fe_url = url(base_url, "/permissions/grant_tag/{}".format(tag.name))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"permission": TAG_EDIT, "argument": "*"}),
        headers={"X-Grouper-User": user.username},
    )

    assert resp.code == 200
コード例 #2
0
 def get(self):
     self.render(
         "help.html",
         how_to_get_help=settings.how_to_get_help,
         site_docs=settings.site_docs,
         grant_perm=get_permission(self.session, PERMISSION_GRANT),
         create_perm=get_permission(self.session, PERMISSION_CREATE),
         audit_perm=get_permission(self.session, PERMISSION_AUDITOR),
         tag_edit=get_permission(self.session, TAG_EDIT),
     )
コード例 #3
0
ファイル: help.py プロジェクト: yasaswyk/merou
 def get(self, *args, **kwargs):
     # type: (*Any, **Any) -> None
     self.render(
         "help.html",
         how_to_get_help=settings().how_to_get_help,
         site_docs=settings().site_docs,
         grant_perm=get_permission(self.session, PERMISSION_GRANT),
         create_perm=get_permission(self.session, PERMISSION_CREATE),
         audit_perm=get_permission(self.session, PERMISSION_AUDITOR),
     )
コード例 #4
0
def test_revoke_permission_from_tag(users, http_client, base_url, session):  # noqa: F811

    user = session.query(User).filter_by(username="******").scalar()

    create_permission(session, TAG_EDIT)
    session.commit()

    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, TAG_EDIT),
        "*",
    )

    fe_url = url(base_url, "/tags")
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"tagname": "tyler_was_here", "description": "Test Tag Please Ignore"}),
        headers={"X-Grouper-User": user.username},
    )

    tag = PublicKeyTag.get(session, name="tyler_was_here")

    user = session.query(User).filter_by(username="******").scalar()

    fe_url = url(base_url, "/permissions/grant_tag/{}".format(tag.name))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"permission": TAG_EDIT, "argument": "*"}),
        headers={"X-Grouper-User": user.username},
    )

    assert resp.code == 200
    tag = PublicKeyTag.get(session, name="tyler_was_here")
    get_permission(session, TAG_EDIT)
    assert (
        len(get_public_key_tag_permissions(session, tag)) == 1
    ), "The tag should have exactly 1 permission"

    user = session.query(User).filter_by(username="******").scalar()

    mapping = get_public_key_tag_permissions(session, tag)[0]
    fe_url = url(base_url, "/permissions/{}/revoke_tag/{}".format(TAG_EDIT, mapping.mapping_id))
    resp = yield http_client.fetch(
        fe_url, method="POST", body="", headers={"X-Grouper-User": user.username}
    )

    assert resp.code == 200
    tag = PublicKeyTag.get(session, name="tyler_was_here")
    assert (
        len(get_public_key_tag_permissions(session, tag)) == 0
    ), "The tag should have no permissions"
コード例 #5
0
ファイル: handlers_test.py プロジェクト: dropbox/grouper
def test_service_accounts(session, standard_graph, users, http_client, base_url):  # noqa: F811
    api_url = url(base_url, "/service_accounts")
    resp = yield http_client.fetch(api_url)
    body = json.loads(resp.body)
    assert resp.code == 200
    assert body["status"] == "ok"
    assert sorted(body["data"]["service_accounts"]) == sorted(
        [u.name for u in itervalues(users) if u.role_user] + ["*****@*****.**"]
    )

    # Retrieve a single service account and check its metadata.
    api_url = url(base_url, "/service_accounts/[email protected]")
    resp = yield http_client.fetch(api_url)
    body = json.loads(resp.body)
    assert resp.code == 200
    assert body["status"] == "ok"
    data = body["data"]["user"]
    assert "service_account" in data
    assert data["service_account"]["description"] == "some service account"
    assert data["service_account"]["machine_set"] == "some machines"
    assert data["service_account"]["owner"] == "team-sre"
    assert body["data"]["permissions"] == []

    # Delegate a permission to the service account and check for it.
    service_account = ServiceAccount.get(session, name="*****@*****.**")
    permission = get_permission(session, "team-sre")
    grant_permission_to_service_account(session, service_account, permission, "*")
    standard_graph.update_from_db(session)
    resp = yield http_client.fetch(api_url)
    body = json.loads(resp.body)
    assert resp.code == 200
    assert body["status"] == "ok"
    perms = body["data"]["permissions"]
    assert perms[0]["permission"] == "team-sre"
    assert perms[0]["argument"] == "*"
コード例 #6
0
    def post(self, name=None):
        tag = PublicKeyTag.get(self.session, None, name)
        if not tag:
            return self.notfound()

        if not user_has_permission(self.session, self.current_user, TAG_EDIT,
                                   tag.name):
            return self.forbidden()

        form = PermissionGrantTagForm(self.request.arguments)
        form.permission.choices = [["", "(select one)"]]

        for perm in get_all_permissions(self.session):
            form.permission.choices.append(
                [perm.name, "{} (*)".format(perm.name)])

        if not form.validate():
            return self.render(
                "permission-grant-tag.html",
                form=form,
                tag=tag,
                alerts=self.get_form_alerts(form.errors),
            )

        permission = get_permission(self.session, form.data["permission"])
        if not permission:
            return self.notfound()  # Shouldn't happen.

        success = grant_permission_to_tag(self.session,
                                          tag.id,
                                          permission.id,
                                          argument=form.data["argument"])

        if not success:
            form.argument.errors.append(
                "Permission and Argument already mapped to this tag.")
            return self.render(
                "permission-grant-tag.html",
                form=form,
                tag=tag,
                alerts=self.get_form_alerts(form.errors),
            )

        AuditLog.log(
            self.session,
            self.current_user.id,
            "grant_permission_tag",
            "Granted permission with argument: {}".format(
                form.data["argument"]),
            on_permission_id=permission.id,
            on_tag_id=tag.id,
        )

        return self.redirect("/tags/{}?refresh=yes".format(tag.name))
コード例 #7
0
def test_permission_disable(setup):
    # type: (SetupTest) -> None
    with setup.transaction():
        setup.grant_permission_to_group(PERMISSION_ADMIN, "", "admins")
        setup.add_user_to_group("*****@*****.**", "admins")
        setup.create_permission("some-permission")

    run_ctl(setup, "permission", "-a", "*****@*****.**", "disable",
            "some-permission")
    permission = get_permission(setup.session, "some-permission")
    assert permission
    assert not permission.enabled
コード例 #8
0
ファイル: models_test.py プロジェクト: yasaswyk/merou
def test_permission_exclude_inactive_groups(session,
                                            standard_graph):  # noqa: F811
    """Ensure disabled groups are excluded from permission data."""
    group = Group.get(session, name="team-sre")
    permission = get_permission(session, "ssh")
    assert "team-sre" in [
        g[0] for g in get_groups_by_permission(session, permission)
    ]
    group.disable()
    assert "team-sre" not in [
        g[0] for g in get_groups_by_permission(session, permission)
    ]
コード例 #9
0
ファイル: tags_test.py プロジェクト: brandon-rhodes/merou
def test_edit_tag(users, http_client, base_url, session):  # noqa: F811

    user = session.query(User).filter_by(username="******").scalar()

    create_permission(session, TAG_EDIT)
    session.commit()

    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, TAG_EDIT),
        "*",
    )

    fe_url = url(base_url, "/tags")
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({
            "tagname": "tyler_was_here",
            "description": "Test Tag Please Ignore"
        }),
        headers={"X-Grouper-User": user.username},
    )

    tag = PublicKeyTag.get(session, name="tyler_was_here")

    assert (tag.description == "Test Tag Please Ignore"
            ), "The description should match what we created it with"

    user = session.query(User).filter_by(username="******").scalar()
    fe_url = url(base_url, "/tags/{}/edit".format(tag.id))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"description": "Don't tag me bro"}),
        headers={"X-Grouper-User": user.username},
    )

    assert resp.code == 200

    tag = PublicKeyTag.get(session, name="tyler_was_here")

    assert tag.description == "Don't tag me bro", "The description should have been updated"
コード例 #10
0
    def get(self, name=None):
        # TODO: use cached data instead, add refresh to appropriate redirects.
        permission = get_permission(self.session, name)
        if not permission:
            return self.notfound()

        can_change_audit_status = user_is_permission_admin(
            self.session, self.current_user)
        can_disable = user_is_permission_admin(self.session, self.current_user)
        mapped_groups = get_groups_by_permission(self.session, permission)
        log_entries = get_log_entries_by_permission(self.session, permission)

        self.render(
            "permission.html",
            permission=permission,
            can_disable=can_disable,
            mapped_groups=mapped_groups,
            log_entries=log_entries,
            can_change_audit_status=can_change_audit_status,
        )
コード例 #11
0
def test_service_accounts(session, standard_graph, users, http_client,
                          base_url):  # noqa: F811
    api_url = url(base_url, "/service_accounts")
    resp = yield http_client.fetch(api_url)
    body = json.loads(resp.body)
    assert resp.code == 200
    assert body["status"] == "ok"
    assert sorted(body["data"]["service_accounts"]) == sorted(
        [u.name for u in itervalues(users) if u.role_user] + ["*****@*****.**"])

    # TODO: test cutoff

    # Retrieve a single service account and check its metadata.
    api_url = url(base_url, "/service_accounts/[email protected]")
    resp = yield http_client.fetch(api_url)
    body = json.loads(resp.body)
    assert resp.code == 200
    assert body["status"] == "ok"
    data = body["data"]["user"]
    assert "service_account" in data
    assert data["service_account"]["description"] == "some service account"
    assert data["service_account"]["machine_set"] == "some machines"
    assert data["service_account"]["owner"] == "team-sre"
    assert body["data"]["permissions"] == []

    # Delegate a permission to the service account and check for it.
    service_account = ServiceAccount.get(session, name="*****@*****.**")
    permission = get_permission(session, "team-sre")
    grant_permission_to_service_account(session, service_account, permission,
                                        "*")
    standard_graph.update_from_db(session)
    resp = yield http_client.fetch(api_url)
    body = json.loads(resp.body)
    assert resp.code == 200
    assert body["status"] == "ok"
    perms = body["data"]["permissions"]
    assert perms[0]["permission"] == "team-sre"
    assert perms[0]["argument"] == "*"
コード例 #12
0
    def post(self, name=None):
        grantable = user_grantable_permissions(self.session, self.current_user)
        if not grantable:
            return self.forbidden()

        group = Group.get(self.session, None, name)
        if not group:
            return self.notfound()

        form = PermissionGrantForm(self.request.arguments)
        form.permission.choices = [["", "(select one)"]]
        for perm in grantable:
            grantable_str = "{} ({})".format(perm[0].name, perm[1])
            form.permission.choices.append([perm[0].name, grantable_str])

        if not form.validate():
            return self.render(
                "permission-grant.html",
                form=form,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )

        permission = get_permission(self.session, form.data["permission"])
        if not permission:
            return self.notfound()  # Shouldn't happen.

        allowed = False
        for perm in grantable:
            if perm[0].name == permission.name:
                if matches_glob(perm[1], form.data["argument"]):
                    allowed = True
                    break
        if not allowed:
            form.argument.errors.append(
                "You do not have grant authority over that permission/argument combination."
            )
            return self.render(
                "permission-grant.html",
                form=form,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )

        # If the permission is audited, then see if the subtree meets auditing requirements.
        if permission.audited:
            fail_message = (
                "Permission is audited and this group (or a subgroup) contains "
                +
                "owners, np-owners, or managers who have not received audit training."
            )
            try:
                permission_ok = assert_controllers_are_auditors(group)
            except UserNotAuditor as e:
                permission_ok = False
                fail_message = e
            if not permission_ok:
                form.permission.errors.append(fail_message)
                return self.render(
                    "permission-grant.html",
                    form=form,
                    group=group,
                    alerts=self.get_form_alerts(form.errors),
                )

        try:
            grant_permission(self.session,
                             group.id,
                             permission.id,
                             argument=form.data["argument"])
        except IntegrityError:
            self.session.rollback()
            form.argument.errors.append(
                "Permission and Argument already mapped to this group.")
            return self.render(
                "permission-grant.html",
                form=form,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )

        self.session.commit()

        AuditLog.log(
            self.session,
            self.current_user.id,
            "grant_permission",
            "Granted permission with argument: {}".format(
                form.data["argument"]),
            on_permission_id=permission.id,
            on_group_id=group.id,
        )

        return self.redirect("/groups/{}?refresh=yes".format(group.name))
コード例 #13
0
    def post(self, *args, **kwargs):
        # type: (*Any, **Any) -> None
        group_id = kwargs.get("group_id")  # type: Optional[int]
        name = kwargs.get("name")  # type: Optional[str]

        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        # Only members can request permissions
        if not self.current_user.is_member(group.my_members()):
            return self.forbidden()

        # check inputs
        args_by_perm = get_grantable_permissions(
            self.session, settings().restricted_ownership_permissions
        )
        dropdown_form, text_form = GroupPermissionRequest._get_forms(
            args_by_perm, self.request.arguments
        )

        argument_type = self.request.arguments.get("argument_type")
        if argument_type and argument_type[0].decode() == "text":
            form = text_form
        elif argument_type and argument_type[0].decode() == "dropdown":
            form = dropdown_form
            form.argument.choices = [(a, a) for a in args_by_perm[form.permission_name.data]]
        else:
            # someone messing with the form
            self.log_message(
                "unknown argument type", group_name=group.name, argument_type=argument_type
            )
            return self.forbidden()

        if not form.validate():
            return self.render(
                "group-permission-request.html",
                dropdown_form=dropdown_form,
                text_form=text_form,
                group=group,
                args_by_perm_json=json.dumps(args_by_perm),
                alerts=self.get_form_alerts(form.errors),
                dropdown_help=settings().permission_request_dropdown_help,
                text_help=settings().permission_request_text_help,
            )

        permission = get_permission(self.session, form.permission_name.data)
        assert permission is not None, "our prefilled permission should exist or we have problems"

        # save off request
        try:
            request = permissions.create_request(
                self.session,
                self.current_user,
                group,
                permission,
                form.argument.data,
                form.reason.data,
            )
        except permissions.RequestAlreadyGranted:
            alerts = [Alert("danger", "This group already has this permission and argument.")]
        except permissions.RequestAlreadyExists:
            alerts = [
                Alert(
                    "danger",
                    "Request for permission and argument already exists, please wait patiently.",
                )
            ]
        except permissions.NoOwnersAvailable:
            self.log_message(
                "prefilled perm+arg have no owner",
                group_name=group.name,
                permission_name=permission.name,
                argument=form.argument.data,
            )
            alerts = [
                Alert(
                    "danger",
                    "No owners available for requested permission and argument."
                    " If this error persists please contact an adminstrator.",
                )
            ]
        except UserNotAuditor as e:
            alerts = [Alert("danger", str(e))]
        else:
            alerts = []

        if alerts:
            return self.render(
                "group-permission-request.html",
                dropdown_form=dropdown_form,
                text_form=text_form,
                group=group,
                args_by_perm_json=json.dumps(args_by_perm),
                alerts=alerts,
            )
        else:
            return self.redirect("/permissions/requests/{}".format(request.id))
コード例 #14
0
def test_permissions(users, http_client, base_url, session):  # noqa: F811

    user = session.query(User).filter_by(username="******").scalar()

    create_permission(session, TAG_EDIT)
    session.commit()

    create_permission(session, "it.literally.does.not.matter")
    session.commit()

    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, TAG_EDIT),
        "*",
    )
    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, "it.literally.does.not.matter"),
        "*",
    )

    fe_url = url(base_url, "/tags")
    yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"tagname": "tyler_was_here", "description": "Test Tag Please Ignore"}),
        headers={"X-Grouper-User": user.username},
    )

    tag = PublicKeyTag.get(session, name="tyler_was_here")

    user = session.query(User).filter_by(username="******").scalar()

    fe_url = url(base_url, "/permissions/grant_tag/{}".format(tag.name))
    yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"permission": TAG_EDIT, "argument": "prod"}),
        headers={"X-Grouper-User": user.username},
    )

    user = session.query(User).filter_by(username="******").scalar()
    # add SSH key
    fe_url = url(base_url, "/users/{}/public-key/add".format(user.username))
    yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"public_key": SSH_KEY_1}),
        headers={"X-Grouper-User": user.username},
    )

    key = session.query(PublicKey).filter_by(user_id=user.id).scalar()
    user = session.query(User).filter_by(username="******").scalar()

    fe_url = url(base_url, "/users/{}/public-key/{}/tag".format(user.username, key.id))
    yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"tagname": "tyler_was_here"}),
        headers={"X-Grouper-User": user.username},
    )

    user = session.query(User).filter_by(username="******").scalar()

    key = session.query(PublicKey).filter_by(user_id=user.id).scalar()
    assert (
        len(get_public_key_permissions(session, key)) == 1
    ), "The SSH Key should have only 1 permission"
    assert (
        get_public_key_permissions(session, key)[0].name == TAG_EDIT
    ), "The SSH key's permission should be TAG_EDIT"
    assert (
        get_public_key_permissions(session, key)[0].argument == "prod"
    ), "The SSH key's permission argument should be restricted to the tag's argument"
    assert len(user_permissions(session, user)) > 1, "The user should have more than 1 permission"
コード例 #15
0
ファイル: permissions_test.py プロジェクト: dropbox/grouper
def test_grant_and_revoke(
    session, standard_graph, graph, groups, permissions, http_client, base_url  # noqa: F811
):
    """Test that permission grant and revokes are reflected correctly."""
    group_name = "team-sre"
    permission_name = "sudo"
    user_name = "*****@*****.**"

    def _check_graph_for_perm(graph):
        # type: (GroupGraph) -> bool
        return any(
            [
                g["permission"] == permission_name and g["distance"] == 0
                for g in graph.get_group_details(group_name)["permissions"]
            ]
        )

    # make some permission admins
    grant_permission(groups["security-team"], permissions[PERMISSION_ADMIN])

    # grant attempt by non-permission admin
    fe_url = url(base_url, "/permissions/grant/{}".format(group_name))
    with pytest.raises(HTTPError):
        yield http_client.fetch(
            fe_url,
            method="POST",
            body=urlencode({"permission": permission_name, "argument": "specific_arg"}),
            headers={"X-Grouper-User": "******"},
        )

    graph.update_from_db(session)
    assert not _check_graph_for_perm(graph), "no permissions granted"

    # grant by permission admin
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"permission": permission_name, "argument": "specific_arg"}),
        headers={"X-Grouper-User": user_name},
    )
    assert resp.code == 200

    graph.update_from_db(session)
    assert _check_graph_for_perm(graph), "permissions granted, successfully"

    # figure out mapping_id of grant
    permission_id = get_permission(session, permission_name).id
    group_id = Group.get(session, name=group_name).id
    mapping = (
        session.query(PermissionMap)
        .filter(PermissionMap.permission_id == permission_id, PermissionMap.group_id == group_id)
        .first()
    )

    # revoke permission by non-admin
    fe_url = url(base_url, "/permissions/{}/revoke/{}".format(permission_name, mapping.id))
    with pytest.raises(HTTPError):
        yield http_client.fetch(
            fe_url, method="POST", body=urlencode({}), headers={"X-Grouper-User": "******"}
        )

    graph.update_from_db(session)
    assert _check_graph_for_perm(graph), "permissions not revoked"

    # revoke permission for realz
    resp = yield http_client.fetch(
        fe_url, method="POST", body=urlencode({}), headers={"X-Grouper-User": user_name}
    )
    assert resp.code == 200

    graph.update_from_db(session)
    assert not _check_graph_for_perm(graph), "permissions revoked successfully"
コード例 #16
0
    def post(self, group_id=None, name=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()

        # Only members can request permissions
        if not self.current_user.is_member(group.my_members()):
            return self.forbidden()

        # check inputs
        args_by_perm = get_grantable_permissions(
            self.session, settings.restricted_ownership_permissions)
        dropdown_form, text_form = GroupPermissionRequest._get_forms(
            args_by_perm, self.request.arguments)

        argument_type = self.request.arguments.get("argument_type")
        if argument_type and argument_type[0].decode() == "text":
            form = text_form
        elif argument_type and argument_type[0].decode() == "dropdown":
            form = dropdown_form
            form.argument.choices = [
                (a, a) for a in args_by_perm[form.permission_name.data]
            ]
        else:
            # someone messing with the form
            self.log_message("unknown argument type",
                             group_name=group.name,
                             argument_type=argument_type)
            return self.forbidden()

        if not form.validate():
            return self.render(
                "group-permission-request.html",
                dropdown_form=dropdown_form,
                text_form=text_form,
                group=group,
                args_by_perm_json=json.dumps(args_by_perm),
                alerts=self.get_form_alerts(form.errors),
                dropdown_help=settings.permission_request_dropdown_help,
                text_help=settings.permission_request_text_help,
            )

        permission = get_permission(self.session, form.permission_name.data)
        assert permission is not None, "our prefilled permission should exist or we have problems"

        # save off request
        try:
            request = permissions.create_request(
                self.session,
                self.current_user,
                group,
                permission,
                form.argument.data,
                form.reason.data,
            )
        except permissions.RequestAlreadyGranted:
            alerts = [
                Alert("danger",
                      "This group already has this permission and argument.")
            ]
        except permissions.RequestAlreadyExists:
            alerts = [
                Alert(
                    "danger",
                    "Request for permission and argument already exists, please wait patiently.",
                )
            ]
        except permissions.NoOwnersAvailable:
            self.log_message(
                "prefilled perm+arg have no owner",
                group_name=group.name,
                permission_name=permission.name,
                argument=form.argument.data,
            )
            alerts = [
                Alert(
                    "danger",
                    "No owners available for requested permission and argument."
                    " If this error persists please contact an adminstrator.",
                )
            ]
        except UserNotAuditor as e:
            alerts = [Alert("danger", str(e))]
        else:
            alerts = None

        if alerts:
            return self.render(
                "group-permission-request.html",
                dropdown_form=dropdown_form,
                text_form=text_form,
                group=group,
                args_by_perm_json=json.dumps(args_by_perm),
                alerts=alerts,
            )
        else:
            return self.redirect("/permissions/requests/{}".format(request.id))
コード例 #17
0
def test_exclude_disabled_permissions(
    session, standard_graph, graph, users, groups, permissions  # noqa: F811
):
    """
    Ensure that disabled permissions are excluded from various
    functions/methods that return data from the models.
    """
    perm_ssh = get_permission(session, "ssh")
    perm_grant = create_permission(session, PERMISSION_GRANT)
    session.commit()
    # this user has grouper.permission.grant with argument "ssh/*"
    grant_permission(groups["group-admins"], perm_grant, argument="ssh/*")
    graph.update_from_db(session)

    grant_perms = [
        x for x in user_permissions(session, users["*****@*****.**"]) if x.name == PERMISSION_GRANT
    ]
    assert "ssh" == filter_grantable_permissions(session, grant_perms)[0][0].name
    assert "ssh" in (p.name for p in get_all_permissions(session))
    assert "ssh" in (p.name for p in get_all_permissions(session, include_disabled=False))
    assert "ssh" in (p.name for p in get_all_permissions(session, include_disabled=True))
    assert "ssh" in get_grantable_permissions(session, [])
    assert "team-sre" in [g[0] for g in get_groups_by_permission(session, perm_ssh)]
    assert get_owner_arg_list(session, perm_ssh, "*")
    assert "ssh" in get_owners_by_grantable_permission(session)
    assert "ssh" in (x[0].name for x in user_grantable_permissions(session, users["*****@*****.**"]))
    assert user_has_permission(session, users["*****@*****.**"], "ssh")
    assert "ssh" in (p.name for p in user_permissions(session, users["*****@*****.**"]))
    assert "ssh" in (p["permission"] for p in graph.get_group_details("team-sre")["permissions"])
    assert "ssh" in (pt.name for pt in graph.get_permissions())
    assert "team-sre" in graph.get_permission_details("ssh")["groups"]
    assert "ssh" in (p["permission"] for p in graph.get_user_details("*****@*****.**")["permissions"])

    # now disable the ssh permission
    disable_permission(session, "ssh", users["*****@*****.**"].id)
    graph.update_from_db(session)

    grant_perms = [
        x for x in user_permissions(session, users["*****@*****.**"]) if x.name == PERMISSION_GRANT
    ]
    assert not filter_grantable_permissions(session, grant_perms)
    assert "ssh" not in (p.name for p in get_all_permissions(session))
    assert "ssh" not in (p.name for p in get_all_permissions(session, include_disabled=False))
    assert "ssh" in (p.name for p in get_all_permissions(session, include_disabled=True))
    assert "ssh" not in get_grantable_permissions(session, [])
    assert not get_groups_by_permission(session, perm_ssh)
    assert not get_owner_arg_list(session, perm_ssh, "*")
    assert "ssh" not in get_owners_by_grantable_permission(session)
    assert "ssh" not in (
        x[0].name for x in user_grantable_permissions(session, users["*****@*****.**"])
    )
    assert not user_has_permission(session, users["*****@*****.**"], "ssh")
    assert "ssh" not in (p.name for p in user_permissions(session, users["*****@*****.**"]))
    assert "ssh" not in (
        p["permission"] for p in graph.get_group_details("team-sre")["permissions"]
    )
    assert "ssh" not in (pt.name for pt in graph.get_permissions())
    assert not graph.get_permission_details("ssh")["groups"]
    assert "ssh" not in (
        p["permission"] for p in graph.get_user_details("*****@*****.**")["permissions"]
    )
コード例 #18
0
    def post(self, *args: Any, **kwargs: Any) -> None:
        name = self.get_path_argument("name")

        grantable = user_grantable_permissions(self.session, self.current_user)
        if not grantable:
            return self.forbidden()

        group = Group.get(self.session, name=name)
        if not group:
            return self.notfound()

        form = PermissionGrantForm(self.request.arguments)
        form.permission.choices = [["", "(select one)"]]
        for perm in grantable:
            grantable_str = "{} ({})".format(perm[0].name, perm[1])
            form.permission.choices.append([perm[0].name, grantable_str])

        if not form.validate():
            return self.render(
                "permission-grant.html",
                form=form,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )

        permission = get_permission(self.session, form.data["permission"])
        if not permission:
            return self.notfound()  # Shouldn't happen.

        argument = form.argument.data.strip()

        allowed = False
        for perm in grantable:
            if perm[0].name == permission.name:
                if matches_glob(perm[1], argument):
                    allowed = True
                    break
        if not allowed:
            form.argument.errors.append(
                "You do not have grant authority over that permission/argument combination."
            )
            return self.render(
                "permission-grant.html",
                form=form,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )

        # If the permission is audited, then see if the subtree meets auditing requirements.
        if permission.audited:
            try:
                assert_controllers_are_auditors(group)
            except UserNotAuditor as e:
                form.permission.errors.append(str(e))
                return self.render(
                    "permission-grant.html",
                    form=form,
                    group=group,
                    alerts=self.get_form_alerts(form.errors),
                )

        try:
            self.plugins.check_permission_argument(permission.name, argument)
            grant_permission(self.session,
                             group.id,
                             permission.id,
                             argument=argument)
        except PluginRejectedPermissionArgument as e:
            self.session.rollback()
            form.argument.errors.append(f"Rejected by plugin: {e}")
            return self.render(
                "permission-grant.html",
                form=form,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )
        except IntegrityError:
            self.session.rollback()
            form.argument.errors.append(
                "Permission and Argument already mapped to this group.")
            return self.render(
                "permission-grant.html",
                form=form,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )

        self.session.commit()

        AuditLog.log(
            self.session,
            self.current_user.id,
            "grant_permission",
            "Granted permission with argument: {}".format(
                form.data["argument"]),
            on_permission_id=permission.id,
            on_group_id=group.id,
        )

        return self.redirect("/groups/{}?refresh=yes".format(group.name))
コード例 #19
0
ファイル: permission_request.py プロジェクト: Warrelis/merou
    def post(self, *args, **kwargs):
        # type: (*Any, **Any) -> None
        form, args_by_perm = self._build_form(self.request.arguments)

        if not form.validate():
            return self.render(
                "permission-request.html",
                args_by_perm_json=json.dumps(args_by_perm),
                form=form,
                alerts=self.get_form_alerts(form.errors),
            )

        group = Group.get(self.session, name=form.group_name.data)
        if group is None:
            raise HTTPError(status_code=400, reason="that group does not exist")

        permission = get_permission(self.session, form.permission_name.data)
        if permission is None:
            raise HTTPError(status_code=400, reason="that permission does not exist")

        if permission.name not in args_by_perm:
            raise HTTPError(status_code=400, reason="that permission was not in the form")

        # save off request
        try:
            request = permissions.create_request(
                self.session,
                self.current_user,
                group,
                permission,
                form.argument.data,
                form.reason.data,
            )
        except permissions.RequestAlreadyGranted:
            alerts = [Alert("danger", "This group already has this permission and argument.")]
        except permissions.RequestAlreadyExists:
            alerts = [
                Alert(
                    "danger",
                    "Request for permission and argument already exists, please wait patiently.",
                )
            ]
        except permissions.NoOwnersAvailable:
            self.log_message(
                "prefilled perm+arg have no owner",
                group_name=group.name,
                permission_name=permission.name,
                argument=form.argument.data,
            )
            alerts = [
                Alert(
                    "danger",
                    "No owners available for requested permission and argument."
                    " If this error persists please contact an adminstrator.",
                )
            ]
        except UserNotAuditor as e:
            alerts = [Alert("danger", str(e))]
        else:
            alerts = []

        if alerts:
            return self.render(
                "permission-request.html",
                args_by_perm_json=json.dumps(args_by_perm),
                form=form,
                alerts=alerts,
            )
        else:
            return self.redirect("/permissions/requests/{}".format(request.id))
コード例 #20
0
    def post(self,
             group_id=None,
             name=None,
             account_id=None,
             accountname=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()
        service_account = ServiceAccount.get(self.session, account_id,
                                             accountname)
        if not service_account:
            return self.notfound()
        user = service_account.user

        if not self.check_access(self.session, self.current_user,
                                 service_account):
            return self.forbidden()

        grantable = group.my_permissions()
        form = self.get_form(grantable)
        if not form.validate():
            return self.render(
                "service-account-permission-grant.html",
                form=form,
                user=user,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )

        permission = get_permission(self.session, form.data["permission"])
        if not permission:
            return self.notfound()

        allowed = False
        for perm in grantable:
            if perm[1] == permission.name:
                if matches_glob(perm[3], form.data["argument"]):
                    allowed = True
                    break
        if not allowed:
            form.argument.errors.append(
                "The group {} does not have that permission".format(
                    group.name))
            return self.render(
                "service-account-permission-grant.html",
                form=form,
                user=user,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )

        try:
            grant_permission_to_service_account(self.session, service_account,
                                                permission,
                                                form.data["argument"])
        except IntegrityError:
            self.session.rollback()
            return self.render(
                "service-account-permission-grant.html",
                form=form,
                user=user,
                alerts=self.get_form_alerts(form.errors),
            )

        AuditLog.log(
            self.session,
            self.current_user.id,
            "grant_permission",
            "Granted permission with argument: {}".format(
                form.data["argument"]),
            on_permission_id=permission.id,
            on_group_id=group.id,
            on_user_id=service_account.user.id,
        )

        return self.redirect("/groups/{}/service/{}?refresh=yes".format(
            group.name, service_account.user.username))
コード例 #21
0
def test_tags(session, http_client, base_url, graph):  # noqa: F811
    perm = create_permission(session, TAG_EDIT)
    session.commit()

    create_permission(session, "it.literally.does.not.matter")
    session.commit()

    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, TAG_EDIT),
        "*",
    )
    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, "it.literally.does.not.matter"),
        "*",
    )

    tag = PublicKeyTag(name="tyler_was_here")
    tag.add(session)
    session.commit()

    tag = PublicKeyTag.get(session, name="tyler_was_here")

    grant_permission_to_tag(session, tag.id, perm.id, "prod")
    with pytest.raises(AssertionError):
        grant_permission_to_tag(session, tag.id, perm.id, "question?")

    user = session.query(User).filter_by(username="******").scalar()

    add_public_key(session, user, SSH_KEY_1)

    key = session.query(PublicKey).filter_by(user_id=user.id).scalar()

    add_tag_to_public_key(session, key, tag)

    user = session.query(User).filter_by(username="******").scalar()

    key = session.query(PublicKey).filter_by(user_id=user.id).scalar()
    assert (
        len(get_public_key_permissions(session, key)) == 1
    ), "The SSH Key should have only 1 permission"
    assert (
        get_public_key_permissions(session, key)[0].name == TAG_EDIT
    ), "The SSH key's permission should be TAG_EDIT"
    assert (
        get_public_key_permissions(session, key)[0].argument == "prod"
    ), "The SSH key's permission argument should be restricted to the tag's argument"
    assert len(user_permissions(session, user)) > 1, "The user should have more than 1 permission"

    graph.update_from_db(session)

    fe_url = url(base_url, "/users/{}".format(user.username))
    resp = yield http_client.fetch(fe_url)
    assert resp.code == 200
    body = json.loads(resp.body)
    pub_key = body["data"]["user"]["public_keys"][0]
    assert len(pub_key["tags"]) == 1, "The public key should only have 1 tag"
    assert pub_key["fingerprint"] == "e9:ae:c5:8f:39:9b:3a:9c:6a:b8:33:6b:cb:6f:ba:35"
    assert pub_key["fingerprint_sha256"] == "MP9uWaujW96EWxbjDtPdPWheoMDu6BZ8FZj0+CBkVWU"
    assert pub_key["tags"][0] == "tyler_was_here", "The public key should have the tag we gave it"
コード例 #22
0
ファイル: permissions_grant.py プロジェクト: dropbox/grouper
    def post(self, name=None):
        grantable = user_grantable_permissions(self.session, self.current_user)
        if not grantable:
            return self.forbidden()

        group = Group.get(self.session, None, name)
        if not group:
            return self.notfound()

        form = PermissionGrantForm(self.request.arguments)
        form.permission.choices = [["", "(select one)"]]
        for perm in grantable:
            grantable_str = "{} ({})".format(perm[0].name, perm[1])
            form.permission.choices.append([perm[0].name, grantable_str])

        if not form.validate():
            return self.render(
                "permission-grant.html",
                form=form,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )

        permission = get_permission(self.session, form.data["permission"])
        if not permission:
            return self.notfound()  # Shouldn't happen.

        allowed = False
        for perm in grantable:
            if perm[0].name == permission.name:
                if matches_glob(perm[1], form.data["argument"]):
                    allowed = True
                    break
        if not allowed:
            form.argument.errors.append(
                "You do not have grant authority over that permission/argument combination."
            )
            return self.render(
                "permission-grant.html",
                form=form,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )

        # If the permission is audited, then see if the subtree meets auditing requirements.
        if permission.audited:
            fail_message = (
                "Permission is audited and this group (or a subgroup) contains "
                + "owners, np-owners, or managers who have not received audit training."
            )
            try:
                permission_ok = assert_controllers_are_auditors(group)
            except UserNotAuditor as e:
                permission_ok = False
                fail_message = e
            if not permission_ok:
                form.permission.errors.append(fail_message)
                return self.render(
                    "permission-grant.html",
                    form=form,
                    group=group,
                    alerts=self.get_form_alerts(form.errors),
                )

        try:
            grant_permission(self.session, group.id, permission.id, argument=form.data["argument"])
        except IntegrityError:
            self.session.rollback()
            form.argument.errors.append("Permission and Argument already mapped to this group.")
            return self.render(
                "permission-grant.html",
                form=form,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )

        self.session.commit()

        AuditLog.log(
            self.session,
            self.current_user.id,
            "grant_permission",
            "Granted permission with argument: {}".format(form.data["argument"]),
            on_permission_id=permission.id,
            on_group_id=group.id,
        )

        return self.redirect("/groups/{}?refresh=yes".format(group.name))
コード例 #23
0
ファイル: permissions_test.py プロジェクト: bsittler/merou
def test_grant_and_revoke(
        session,
        standard_graph,
        graph,
        groups,
        permissions,
        http_client,
        base_url  # noqa: F811
):
    """Test that permission grant and revokes are reflected correctly."""
    group_name = "team-sre"
    permission_name = "sudo"
    user_name = "*****@*****.**"

    def _check_graph_for_perm(graph):
        # type: (GroupGraph) -> bool
        return any([
            g["permission"] == permission_name and g["distance"] == 0
            for g in graph.get_group_details(group_name)["permissions"]
        ])

    # make some permission admins
    grant_permission(groups["security-team"], permissions[PERMISSION_ADMIN])

    # grant attempt by non-permission admin
    fe_url = url(base_url, "/permissions/grant/{}".format(group_name))
    with pytest.raises(HTTPError):
        yield http_client.fetch(
            fe_url,
            method="POST",
            body=urlencode({
                "permission": permission_name,
                "argument": "specific_arg"
            }),
            headers={"X-Grouper-User": "******"},
        )

    graph.update_from_db(session)
    assert not _check_graph_for_perm(graph), "no permissions granted"

    # grant by permission admin
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({
            "permission": permission_name,
            "argument": "specific_arg"
        }),
        headers={"X-Grouper-User": user_name},
    )
    assert resp.code == 200

    graph.update_from_db(session)
    assert _check_graph_for_perm(graph), "permissions granted, successfully"

    # figure out mapping_id of grant
    permission_id = get_permission(session, permission_name).id
    group_id = Group.get(session, name=group_name).id
    mapping = (session.query(PermissionMap).filter(
        PermissionMap.permission_id == permission_id,
        PermissionMap.group_id == group_id).first())

    # revoke permission by non-admin
    fe_url = url(
        base_url, "/permissions/{}/revoke/{}".format(permission_name,
                                                     mapping.id))
    with pytest.raises(HTTPError):
        yield http_client.fetch(fe_url,
                                method="POST",
                                body=urlencode({}),
                                headers={"X-Grouper-User": "******"})

    graph.update_from_db(session)
    assert _check_graph_for_perm(graph), "permissions not revoked"

    # revoke permission for realz
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   body=urlencode({}),
                                   headers={"X-Grouper-User": user_name})
    assert resp.code == 200

    graph.update_from_db(session)
    assert not _check_graph_for_perm(graph), "permissions revoked successfully"
コード例 #24
0
ファイル: sync_db.py プロジェクト: bonniech3n/merou
def sync_db_command(args):
    # Models not implicitly or explictly imported above are explicitly imported here
    from grouper.models.perf_profile import PerfProfile  # noqa: F401

    db_engine = get_db_engine(get_database_url(settings))
    Model.metadata.create_all(db_engine)

    # Add some basic database structures we know we will need if they don't exist.
    session = make_session()

    for name, description in SYSTEM_PERMISSIONS:
        test = get_permission(session, name)
        if test:
            continue
        try:
            create_permission(session, name, description)
            session.flush()
        except IntegrityError:
            session.rollback()
            raise Exception("Failed to create permission: %s" % (name, ))
        session.commit()

    # This group is needed to bootstrap a Grouper installation.
    admin_group = Group.get(session, name="grouper-administrators")
    if not admin_group:
        admin_group = Group(
            groupname="grouper-administrators",
            description="Administrators of the Grouper system.",
            canjoin="nobody",
        )

        try:
            admin_group.add(session)
            session.flush()
        except IntegrityError:
            session.rollback()
            raise Exception("Failed to create group: grouper-administrators")

        for permission_name in (GROUP_ADMIN, PERMISSION_ADMIN, USER_ADMIN):
            permission = get_permission(session, permission_name)
            assert permission, "Permission should have been created earlier!"
            grant_permission(session, admin_group.id, permission.id)

        session.commit()

    auditors_group_name = get_auditors_group_name(settings)
    auditors_group = Group.get(session, name=auditors_group_name)
    if not auditors_group:
        auditors_group = Group(
            groupname=auditors_group_name,
            description=
            "Group for auditors, who can be owners of audited groups.",
            canjoin="canjoin",
        )

        try:
            auditors_group.add(session)
            session.flush()
        except IntegrityError:
            session.rollback()
            raise Exception(
                "Failed to create group: {}".format(auditors_group_name))

        permission = get_permission(session, PERMISSION_AUDITOR)
        assert permission, "Permission should have been created earlier!"
        grant_permission(session, auditors_group.id, permission.id)

        session.commit()
コード例 #25
0
def test_disabling_permission(
    session, groups, standard_graph, graph, http_client, base_url  # noqa: F811
):
    """
    This tests disabling via the front-end route, including checking
    that the user is authorized to disable permissions.
    """
    perm_name = "sudo"
    nonpriv_user_name = "*****@*****.**"  # user without PERMISSION_ADMIN
    nonpriv_headers = {"X-Grouper-User": nonpriv_user_name}
    priv_user_name = "*****@*****.**"  # user with PERMISSION_ADMIN
    priv_headers = {"X-Grouper-User": priv_user_name}
    disable_url = url(base_url, "/permissions/{}/disable".format(perm_name))
    disable_url_non_exist_perm = url(base_url, "/permissions/no.exists/disable")

    assert "sudo:shell" in get_user_permissions(graph, "*****@*****.**")
    assert "sudo:shell" in get_user_permissions(graph, "*****@*****.**")

    # attempt to disable the permission -> should fail cuz actor
    # doesn't have PERMISSION_ADMIN
    with pytest.raises(HTTPError) as exc:
        yield http_client.fetch(disable_url, method="POST", headers=nonpriv_headers, body="")
    assert exc.value.code == 403
    # check that no change
    assert get_permission(session, perm_name).enabled
    graph.update_from_db(session)
    assert "sudo:shell" in get_user_permissions(graph, "*****@*****.**")
    assert "sudo:shell" in get_user_permissions(graph, "*****@*****.**")

    # an actor with PERMISSION_ADMIN is allowed to disable the
    # permission
    resp = yield http_client.fetch(disable_url, method="POST", headers=priv_headers, body="")
    assert resp.code == 200
    assert not get_permission(session, perm_name).enabled
    graph.update_from_db(session)
    assert "sudo:shell" not in get_user_permissions(graph, "*****@*****.**")
    assert "sudo:shell" not in get_user_permissions(graph, "*****@*****.**")

    with pytest.raises(HTTPError) as exc:
        yield http_client.fetch(
            disable_url_non_exist_perm, method="POST", headers=priv_headers, body=""
        )
    assert exc.value.code == 404

    #
    # make sure that when disabling the permission, all mappings of
    # it, i.e., with different arguments, are disabled
    #

    # the standard_graph grants 'ssh' with args '*' and 'shell' to two
    # different groups
    assert "ssh:*" in get_group_permissions(graph, "team-sre")
    assert "ssh:shell" in get_group_permissions(graph, "tech-ops")
    # disable the perm
    disable_url_ssh_pem = url(base_url, "/permissions/ssh/disable")
    resp = yield http_client.fetch(
        disable_url_ssh_pem, method="POST", headers=priv_headers, body=""
    )
    assert resp.code == 200
    assert not get_permission(session, "ssh").enabled
    graph.update_from_db(session)
    assert "ssh:*" not in get_group_permissions(graph, "team-sre")
    assert "ssh:shell" not in get_group_permissions(graph, "tech-ops")
コード例 #26
0
    def post(self, group_id=None, name=None, account_id=None, accountname=None):
        group = Group.get(self.session, group_id, name)
        if not group:
            return self.notfound()
        service_account = ServiceAccount.get(self.session, account_id, accountname)
        if not service_account:
            return self.notfound()
        user = service_account.user

        if not self.check_access(self.session, self.current_user, service_account):
            return self.forbidden()

        grantable = group.my_permissions()
        form = self.get_form(grantable)
        if not form.validate():
            return self.render(
                "service-account-permission-grant.html",
                form=form,
                user=user,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )

        permission = get_permission(self.session, form.data["permission"])
        if not permission:
            return self.notfound()

        allowed = False
        for perm in grantable:
            if perm[1] == permission.name:
                if matches_glob(perm[3], form.data["argument"]):
                    allowed = True
                    break
        if not allowed:
            form.argument.errors.append(
                "The group {} does not have that permission".format(group.name)
            )
            return self.render(
                "service-account-permission-grant.html",
                form=form,
                user=user,
                group=group,
                alerts=self.get_form_alerts(form.errors),
            )

        try:
            grant_permission_to_service_account(
                self.session, service_account, permission, form.data["argument"]
            )
        except IntegrityError:
            self.session.rollback()
            return self.render(
                "service-account-permission-grant.html",
                form=form,
                user=user,
                alerts=self.get_form_alerts(form.errors),
            )

        AuditLog.log(
            self.session,
            self.current_user.id,
            "grant_permission",
            "Granted permission with argument: {}".format(form.data["argument"]),
            on_permission_id=permission.id,
            on_group_id=group.id,
            on_user_id=service_account.user.id,
        )

        return self.redirect(
            "/groups/{}/service/{}?refresh=yes".format(group.name, service_account.user.username)
        )