def grantable_permissions(session, standard_graph): # noqa: F811 perm_grant = create_permission(session, PERMISSION_GRANT) perm0 = create_permission(session, "grantable") perm1 = create_permission(session, "grantable.one") perm2 = create_permission(session, "grantable.two") session.commit() return perm_grant, perm0, perm1, perm2
def grantable_permissions(session, standard_graph): # noqa: F811 perm_grant = create_permission(session, PERMISSION_GRANT) perm0 = create_permission(session, "grantable") perm1 = create_permission(session, "grantable.one") perm2 = create_permission(session, "grantable.two") session.commit() return perm_grant, perm0, perm1, perm2
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"
def post(self): can_create = user_creatable_permissions(self.session, self.current_user) if not can_create: return self.forbidden() form = PermissionCreateForm(self.request.arguments) if not form.validate(): return self.render("permission-create.html", form=form, alerts=self.get_form_alerts(form.errors)) # A user is allowed to create a permission if the name matches any of the globs that they # are given access to via PERMISSION_CREATE, as long as the permission does not match a # reserved name. (Unless specifically granted.) allowed = False for creatable in can_create: if matches_glob(creatable, form.data["name"]): allowed = True for failure_message in test_reserved_names(form.data["name"]): form.name.errors.append(failure_message) if not allowed: form.name.errors.append( "Permission name does not match any of your allowed patterns.") if form.name.errors: return self.render("permission-create.html", form=form, alerts=self.get_form_alerts(form.errors)) try: permission = create_permission(self.session, form.data["name"], form.data["description"]) self.session.flush() except IntegrityError: self.session.rollback() form.name.errors.append( "Name already in use. Permissions must be unique.") return self.render( "permission-create.html", form=form, can_create=can_create, alerts=self.get_form_alerts(form.errors), ) self.session.commit() AuditLog.log( self.session, self.current_user.id, "create_permission", "Created permission.", on_permission_id=permission.id, ) # No explicit refresh because handler queries SQL. return self.redirect("/permissions/{}".format(permission.name))
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
def post(self): can_create = user_creatable_permissions(self.session, self.current_user) if not can_create: return self.forbidden() form = PermissionCreateForm(self.request.arguments) if not form.validate(): return self.render( "permission-create.html", form=form, alerts=self.get_form_alerts(form.errors) ) # A user is allowed to create a permission if the name matches any of the globs that they # are given access to via PERMISSION_CREATE, as long as the permission does not match a # reserved name. (Unless specifically granted.) allowed = False for creatable in can_create: if matches_glob(creatable, form.data["name"]): allowed = True for failure_message in test_reserved_names(form.data["name"]): form.name.errors.append(failure_message) if not allowed: form.name.errors.append("Permission name does not match any of your allowed patterns.") if form.name.errors: return self.render( "permission-create.html", form=form, alerts=self.get_form_alerts(form.errors) ) try: permission = create_permission( self.session, form.data["name"], form.data["description"] ) self.session.flush() except IntegrityError: self.session.rollback() form.name.errors.append("Name already in use. Permissions must be unique.") return self.render( "permission-create.html", form=form, can_create=sorted(can_create), alerts=self.get_form_alerts(form.errors), ) self.session.commit() AuditLog.log( self.session, self.current_user.id, "create_permission", "Created permission.", on_permission_id=permission.id, ) # No explicit refresh because handler queries SQL. return self.redirect("/permissions/{}".format(permission.name))
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"
def test_permission_grant_to_owners( session, standard_graph, groups, grantable_permissions, permissions # noqa: F811 ): """Test we're getting correct owners according to granted 'grouper.permission.grant' permissions.""" perm_grant, _, perm1, perm2 = grantable_permissions # Disable the group with permission admin since otherwise they're an approver on everything, # and check that there are then no approvers. groups["permission-admins"].disable() session.commit() 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.groupname for o, a in get_owner_arg_list( session, perm1, "somesubstring", owners_by_arg_by_perm=owners_by_arg_by_perm) ] assert sorted(res) == ["all-teams", "team-sre" ], "should include substring wildcard matches" res = [ o.groupname for o, a in get_owner_arg_list( session, perm1, "othersubstring", owners_by_arg_by_perm=owners_by_arg_by_perm) ] assert sorted(res) == ["all-teams" ], "negative test of substring wildcard matches" class FakePermissionAliasesPlugin(BasePlugin): def get_aliases_for_mapped_permission(self, session, permission, argument): # type: (Session, str, str) -> List[Tuple[str, str]] if permission != "alias_perm" or argument != "team-sre": return [] return [(PERMISSION_GRANT, "foo-perm/bar-arg")] owner_perm = create_permission(session, "alias_perm") session.commit() get_plugin_proxy().add_plugin(FakePermissionAliasesPlugin()) grant_permission(groups["team-sre"], owner_perm, "team-sre") owners_by_arg_by_perm = get_owners_by_grantable_permission(session) expected = [groups["team-sre"]] assert owners_by_arg_by_perm["foo-perm"]["bar-arg"] == expected # permission admins have all the power grant_permission(groups["security-team"], permissions[PERMISSION_ADMIN]) owners_by_arg_by_perm = get_owners_by_grantable_permission(session) all_permissions = get_all_permissions(session) for perm in all_permissions: assert perm.name in owners_by_arg_by_perm, "all permission should be represented" assert (groups["security-team"] in owners_by_arg_by_perm[perm.name]["*"] ), "permission admin should be wildcard owners"
def 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"
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"] )
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()
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"