def add_public_key(session, user, public_key_str): """Add a public key for a particular user. Args: session: db session user: User model of user in question public_key_str: public key to add Return created PublicKey model or raises DuplicateKey if key is already in use. """ pubkey = sshpubkey.PublicKey.from_str(public_key_str) db_pubkey = PublicKey( user=user, public_key='%s %s %s' % (pubkey.key_type, pubkey.key, pubkey.comment), fingerprint=pubkey.fingerprint, key_size=pubkey.key_size, key_type=pubkey.key_type, ) try: db_pubkey.add(session) Counter.incr(session, "updates") except IntegrityError: session.rollback() raise DuplicateKey() session.commit() return db_pubkey
def grant_permission_to_tag(session, tag_id, permission_id, argument=''): # type: (Session, int, int, str) -> bool """ Grant a permission to this tag. This will fail if the (permission, argument) has already been granted to this tag. Args: session(models.base.session.Sessioan): database session tag_id(int): the id of the tag we're granting the permission to permission_id(int): the id of the permission to be granted argument(str): must match constants.ARGUMENT_VALIDATION Throws: AssertError if argument does not match ARGUMENT_VALIDATION regex Returns: bool indicating whether the function succeeded or not """ assert re.match(ARGUMENT_VALIDATION, argument), 'Permission argument does not match regex.' try: mapping = TagPermissionMap(permission_id=permission_id, tag_id=tag_id, argument=argument) mapping.add(session) Counter.incr(session, "updates") except IntegrityError: session.rollback() return False session.commit() return True
def disable_permission_auditing(session: Session, permission_name: str, actor_user_id: int) -> None: """Set a permission as audited. Args: session: Database session permission_name: Name of permission in question actor_user_id: ID of user who is disabling auditing """ permission = get_permission(session, permission_name) if not permission: raise NoSuchPermission(name=permission_name) permission.audited = False AuditLog.log( session, actor_user_id, "disable_auditing", "Disabled auditing.", on_permission_id=permission.id, ) Counter.incr(session, "updates") session.commit()
def update_status(self, requester, status, reason): now = datetime.utcnow() current_status = self.status self.status = status request_status_change = RequestStatusChange(request=self, user_id=requester.id, from_status=current_status, to_status=status, change_at=now).add( self.session) self.session.flush() Comment(obj_type=OBJ_TYPES_IDX.index("RequestStatusChange"), obj_pk=request_status_change.id, user_id=requester.id, comment=reason, created_on=now).add(self.session) if status == "actioned": edge = self.session.query(GroupEdge).filter_by( id=self.edge_id).one() edge.apply_changes(self) Counter.incr(self.session, "updates")
def test_passwords_api(session, users, http_client, base_url, graph): user = users['*****@*****.**'] TEST_PASSWORD = "******" add_new_user_password(session, "test", TEST_PASSWORD, user.id) assert len(user_passwords(session, user)) == 1, "The user should only have a single password" graph.update_from_db(session) c = Counter.get(session, name="updates") api_url = url(base_url, '/users/{}'.format(user.username)) resp = yield http_client.fetch(api_url) body = json.loads(resp.body) assert body["checkpoint"] == c.count, "The API response is not up to date" assert body["data"]["user"]["passwords"] != [], "The user should not have an empty passwords field" assert body["data"]["user"]["passwords"][0]["name"] == "test", "The password should have the same name" assert body["data"]["user"]["passwords"][0]["func"] == "crypt(3)-$6$", "This test does not support any hash functions other than crypt(3)-$6$" assert body["data"]["user"]["passwords"][0]["hash"] == crypt.crypt(TEST_PASSWORD, body["data"]["user"]["passwords"][0]["salt"]), "The hash should be the same as hashing the password and the salt together using the hashing function" assert body["data"]["user"]["passwords"][0]["hash"] != crypt.crypt("hello", body["data"]["user"]["passwords"][0]["salt"]), "The hash should not be the same as hashing the wrong password and the salt together using the hashing function" delete_user_password(session, "test", user.id) c = Counter.get(session, name="updates") graph.update_from_db(session) api_url = url(base_url, '/users/{}'.format(user.username)) resp = yield http_client.fetch(api_url) body = json.loads(resp.body) assert body["checkpoint"] == c.count, "The API response is not up to date" assert body["data"]["user"]["passwords"] == [], "The user should not have any passwords"
def post(self, name=None, mapping_id=None): mapping = TagPermissionMap.get(self.session, id=mapping_id) if not mapping: return self.notfound() if not user_has_permission(self.session, self.current_user, TAG_EDIT, mapping.tag.name): return self.forbidden() permission = mapping.permission tag = mapping.tag mapping.delete(self.session) Counter.incr(self.session, "updates") self.session.commit() AuditLog.log( self.session, self.current_user.id, "revoke_tag_permission", "Revoked permission with argument: {}".format(mapping.argument), on_tag_id=tag.id, on_permission_id=permission.id, ) return self.redirect("/tags/{}?refresh=yes".format(tag.name))
def set_metadata(self, key, value): if not re.match(PERMISSION_VALIDATION, key): raise ValueError('Metadata key does not match regex.') row = None for try_row in self.my_metadata(): if try_row.data_key == key: row = try_row break if row: if value is None: row.delete(self.session) else: row.data_value = value else: if value is None: # Do nothing, a delete on a key that's not set return else: row = UserMetadata(user_id=self.id, data_key=key, data_value=value) row.add(self.session) Counter.incr(self.session, "updates") self.session.commit()
def post(self, name=None, mapping_id=None): grantable = self.current_user.my_grantable_permissions() if not grantable: return self.forbidden() mapping = PermissionMap.get(self.session, id=mapping_id) if not mapping: return self.notfound() allowed = False for perm in grantable: if perm[0].name == mapping.permission.name: if matches_glob(perm[1], mapping.argument): allowed = True if not allowed: return self.forbidden() permission = mapping.permission group = mapping.group mapping.delete(self.session) Counter.incr(self.session, "updates") self.session.commit() AuditLog.log(self.session, self.current_user.id, 'revoke_permission', 'Revoked permission with argument: {}'.format(mapping.argument), on_group_id=group.id, on_permission_id=permission.id) return self.redirect('/groups/{}?refresh=yes'.format(group.name))
def post(self, name=None, mapping_id=None): mapping = PermissionMap.get(self.session, id=mapping_id) if not mapping: return self.notfound() if not self.check_access(self.session, mapping, self.current_user): return self.forbidden() permission = mapping.permission group = mapping.group mapping.delete(self.session) Counter.incr(self.session, "updates") self.session.commit() AuditLog.log(self.session, self.current_user.id, 'revoke_permission', 'Revoked permission with argument: {}'.format( mapping.argument), on_group_id=group.id, on_permission_id=permission.id) return self.redirect('/groups/{}?refresh=yes'.format(group.name))
def grant_permission_to_service_account(session: Session, account: ServiceAccount, permission: Permission, argument: str = "") -> None: """Grant a permission to this service account. This will fail if the (permission, argument) has already been granted to this group. Args: session: Database session account: A ServiceAccount object being granted a permission permission: A Permission object being granted argument: Must match constants.ARGUMENT_VALIDATION Throws: AssertError if argument does not match ARGUMENT_VALIDATION regex """ assert re.match(ARGUMENT_VALIDATION + r"$", argument), "Invalid permission argument" mapping = ServiceAccountPermissionMap(permission_id=permission.id, service_account_id=account.id, argument=argument) mapping.add(session) Counter.incr(session, "updates") session.commit()
def disable_user(session, user): """Disables an enabled user""" get_plugin_proxy().will_disable_user(session, user) user.enabled = False Counter.incr(session, "updates")
def grant_permission_to_service_account(session, account, permission, argument=""): """ Grant a permission to this service account. This will fail if the (permission, argument) has already been granted to this group. Args: session(models.base.session.Session): database session account(ServiceAccount): a ServiceAccount object being granted a permission permission(Permission): a Permission object being granted argument(str): must match constants.ARGUMENT_VALIDATION Throws: AssertError if argument does not match ARGUMENT_VALIDATION regex """ assert re.match( ARGUMENT_VALIDATION + r"$", argument ), "Permission argument does not match regex." mapping = ServiceAccountPermissionMap( permission_id=permission.id, service_account_id=account.id, argument=argument ) mapping.add(session) Counter.incr(session, "updates") session.commit()
def post(self, tag_id=None, name=None): tag = PublicKeyTag.get(self.session, tag_id, 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 = TagEditForm(self.request.arguments, obj=tag) if not form.validate(): return self.render( "tag-edit.html", tag=tag, form=form, alerts=self.get_form_alerts(form.errors) ) tag.description = form.data["description"] tag.enabled = form.data["enabled"] Counter.incr(self.session, "updates") try: self.session.commit() except IntegrityError: self.session.rollback() form.tagname.errors.append( "{} already exists".format(form.data["tagname"]) ) return self.render( "tag-edit.html", tag=tag, form=form, alerts=self.get_form_alerts(form.errors) ) AuditLog.log(self.session, self.current_user.id, 'edit_tag', 'Edited tag.', on_tag_id=tag.id) return self.redirect("/tags/{}".format(tag.name))
def disable_permission_auditing(session, permission_name, actor_user_id): """Set a permission as audited. Args: session(models.base.session.Session): database session permission_name(str): name of permission in question actor_user_id(int): id of user who is disabling auditing """ permission = get_permission(session, permission_name) if not permission: raise NoSuchPermission(name=permission_name) permission._audited = False AuditLog.log( session, actor_user_id, "disable_auditing", "Disabled auditing.", on_permission_id=permission.id, ) Counter.incr(session, "updates") session.commit()
def grant_permission_to_service_account(session, account, permission, argument=""): """ Grant a permission to this service account. This will fail if the (permission, argument) has already been granted to this group. Args: session(models.base.session.Session): database session account(ServiceAccount): a ServiceAccount object being granted a permission permission(Permission): a Permission object being granted argument(str): must match constants.ARGUMENT_VALIDATION Throws: AssertError if argument does not match ARGUMENT_VALIDATION regex """ assert re.match(ARGUMENT_VALIDATION + r"$", argument), "Permission argument does not match regex." mapping = ServiceAccountPermissionMap(permission_id=permission.id, service_account_id=account.id, argument=argument) mapping.add(session) Counter.incr(session, "updates") session.commit()
def update_status(self, requester, status, reason): now = datetime.utcnow() current_status = self.status self.status = status request_status_change = RequestStatusChange( request=self, user_id=requester.id, from_status=current_status, to_status=status, change_at=now ).add(self.session) self.session.flush() Comment( obj_type=OBJ_TYPES_IDX.index("RequestStatusChange"), obj_pk=request_status_change.id, user_id=requester.id, comment=reason, created_on=now ).add(self.session) if status == "actioned": edge = self.session.query(GroupEdge).filter_by( id=self.edge_id ).one() edge.apply_changes(self) Counter.incr(self.session, "updates")
def grant_permission(session: Session, group_id: int, permission_id: int, argument: str = "") -> None: """Grant a permission to this group. This will fail if the (permission, argument) has already been granted to this group. Args: session: Database session group_id: ID of group to which to grant the permission permission_id: ID of permission to grant argument: Must match constants.ARGUMENT_VALIDATION Throws: AssertError if argument does not match ARGUMENT_VALIDATION regex """ assert re.match(ARGUMENT_VALIDATION + r"$", argument), "Invalid permission argument" mapping = PermissionMap(permission_id=permission_id, group_id=group_id, argument=argument) mapping.add(session) Counter.incr(session, "updates") session.commit()
def post(self, group_id=None, name=None, account_id=None, accountname=None, mapping_id=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() if not self.check_access(self.session, self.current_user, service_account): return self.forbidden() mapping = ServiceAccountPermissionMap.get(self.session, mapping_id) if not mapping: return self.notfound() permission = mapping.permission argument = mapping.argument mapping.delete(self.session) Counter.incr(self.session, "updates") self.session.commit() AuditLog.log(self.session, self.current_user.id, "revoke_permission", "Revoked permission with argument: {}".format(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))
def post(self, *args: Any, **kwargs: Any) -> None: mapping_id = int(self.get_path_argument("mapping_id")) mapping = PermissionMap.get(self.session, id=mapping_id) if not mapping: return self.notfound() if not self.check_access(self.session, mapping, self.current_user): return self.forbidden() permission = mapping.permission group = mapping.group mapping.delete(self.session) Counter.incr(self.session, "updates") self.session.commit() AuditLog.log( self.session, self.current_user.id, "revoke_permission", "Revoked permission with argument: {}".format(mapping.argument), on_group_id=group.id, on_permission_id=permission.id, ) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def post(self): form = TagCreateForm(self.request.arguments) if not form.validate(): return self.render( "tag-create.html", form=form, alerts=self.get_form_alerts(form.errors) ) tag = PublicKeyTag( name=form.data["tagname"], description=form.data["description"], ) try: tag.add(self.session) self.session.flush() except IntegrityError: self.session.rollback() form.tagname.errors.append( "{} already exists".format(form.data["tagname"]) ) return self.render( "tag-create.html", form=form, alerts=self.get_form_alerts(form.errors) ) Counter.incr(self.session, "updates") self.session.commit() AuditLog.log(self.session, self.current_user.id, 'create_tag', 'Created new tag.', on_tag_id=tag.id) return self.redirect("/tags/{}?refresh=yes".format(tag.name))
def grant_permission_to_tag(session, tag_id, permission_id, argument=''): # type: (Session, int, int, str) -> bool """ Grant a permission to this tag. This will fail if the (permission, argument) has already been granted to this tag. Args: session(models.base.session.Sessioan): database session tag_id(int): the id of the tag we're granting the permission to permission_id(int): the id of the permission to be granted argument(str): must match constants.ARGUMENT_VALIDATION Throws: AssertError if argument does not match ARGUMENT_VALIDATION regex Returns: bool indicating whether the function succeeded or not """ assert re.match(ARGUMENT_VALIDATION + r"$", argument), \ 'Permission argument does not match regex.' try: mapping = TagPermissionMap(permission_id=permission_id, tag_id=tag_id, argument=argument) mapping.add(session) Counter.incr(session, "updates") except IntegrityError: session.rollback() return False session.commit() return True
def add_public_key(session, user, public_key_str): """Add a public key for a particular user. Args: session: db session user: User model of user in question public_key_str: public key to add Return created PublicKey model or raises DuplicateKey if key is already in use. """ pubkey = sshpubkeys.SSHKey(public_key_str, strict=True) pubkey.parse() db_pubkey = PublicKey( user=user, public_key=pubkey.keydata.strip(), fingerprint=pubkey.hash_md5().replace(b"MD5:", b""), key_size=pubkey.bits, key_type=pubkey.key_type, ) try: db_pubkey.add(session) Counter.incr(session, "updates") except IntegrityError: session.rollback() raise DuplicateKey() session.commit() return db_pubkey
def post(self, group_id=None, name=None, account_id=None, accountname=None, mapping_id=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() if not self.check_access(self.session, self.current_user, service_account): return self.forbidden() mapping = ServiceAccountPermissionMap.get(self.session, mapping_id) if not mapping: return self.notfound() permission = mapping.permission argument = mapping.argument mapping.delete(self.session) Counter.incr(self.session, "updates") self.session.commit() AuditLog.log( self.session, self.current_user.id, "revoke_permission", "Revoked permission with argument: {}".format(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) )
def disable_permission_auditing(session, permission_name, actor_user_id): """Set a permission as audited. Args: session(models.base.session.Session): database session permission_name(str): name of permission in question actor_user_id(int): id of user who is disabling auditing """ permission = get_permission(session, permission_name) if not permission: raise NoSuchPermission(name=permission_name) permission.audited = False AuditLog.log( session, actor_user_id, "disable_auditing", "Disabled auditing.", on_permission_id=permission.id, ) Counter.incr(session, "updates") session.commit()
def post(self): form = TagCreateForm(self.request.arguments) if not form.validate(): return self.render( "tag-create.html", form=form, alerts=self.get_form_alerts(form.errors) ) tag = PublicKeyTag(name=form.data["tagname"], description=form.data["description"]) try: tag.add(self.session) self.session.flush() except IntegrityError: self.session.rollback() form.tagname.errors.append("{} already exists".format(form.data["tagname"])) return self.render( "tag-create.html", form=form, alerts=self.get_form_alerts(form.errors) ) Counter.incr(self.session, "updates") self.session.commit() AuditLog.log( self.session, self.current_user.id, "create_tag", "Created new tag.", on_tag_id=tag.id ) return self.redirect("/tags/{}?refresh=yes".format(tag.name))
def add_service_account(session, group, service_account): # type: (Session, Group, ServiceAccount) -> None """Add a service account to a group.""" logging.debug("Adding service account %s to %s", service_account.user.username, group.groupname) GroupServiceAccount(group_id=group.id, service_account=service_account).add(session) Counter.incr(session, "updates") session.commit()
def disable_user(session, user): """Disables an enabled user""" for plugin in get_plugins(): plugin.will_disable_user(session, user) user.enabled = False Counter.incr(session, "updates")
def revoke_member(self, requester, user_or_group, reason): """ Revoke a member (User or Group) from this group. Arguments: requester: A User object of the person requesting the addition user_or_group: A User/Group object of the member reason: A comment on why this member should exist """ now = datetime.utcnow() logging.debug( "Revoking member (%s) from %s", user_or_group.name, self.groupname ) # Create the edge even if it doesn't exist so that we can explicitly # disable it. edge, new = GroupEdge.get_or_create( self.session, group_id=self.id, member_type=user_or_group.member_type, member_pk=user_or_group.id, ) self.session.flush() request = Request( requester_id=requester.id, requesting_id=self.id, on_behalf_obj_type=user_or_group.member_type, on_behalf_obj_pk=user_or_group.id, requested_at=now, edge_id=edge.id, status="actioned", changes=build_changes( edge, role="member", expiration=None, active=False ) ).add(self.session) self.session.flush() request_status_change = RequestStatusChange( request=request, user_id=requester.id, to_status="actioned", change_at=now ).add(self.session) self.session.flush() Comment( obj_type=OBJ_TYPES_IDX.index("RequestStatusChange"), obj_pk=request_status_change.id, user_id=requester.id, comment=reason, created_on=now ).add(self.session) edge.apply_changes(request) self.session.flush() Counter.incr(self.session, "updates")
def disable_user_token(session, user_token): """Disable specified user token. Args: session(grouper.models.base.session.Session): database session user_token(grouper.models.user_token.UserToken): token to disable """ user_token.disabled_at = datetime.utcnow() Counter.incr(session, "updates")
def persist_group_member_changes(session, group, requester, member, status, reason, create_edge=False, **updates): requested_at = datetime.utcnow() if "role" in updates: role = updates["role"] _validate_role(member.member_type, role) get_plugin_proxy().will_update_group_membership(session, group, member, **updates) if create_edge: edge = _create_edge(session, group, member, updates.get("role", "member")) else: edge = _get_edge(session, group, member) if not edge: raise MemberNotFound() changes = _serialize_changes(edge, **updates) request = Request( requester_id=requester.id, requesting_id=group.id, on_behalf_obj_type=member.member_type, on_behalf_obj_pk=member.id, requested_at=requested_at, edge_id=edge.id, status=status, changes=changes, ).add(session) session.flush() request_status_change = RequestStatusChange( request=request, user_id=requester.id, to_status=status, change_at=requested_at, ).add(session) session.flush() Comment( obj_type=OBJ_TYPES["RequestStatusChange"], obj_pk=request_status_change.id, user_id=requester.id, comment=reason, created_on=requested_at, ).add(session) session.flush() if status == "actioned": edge.apply_changes(request.changes) session.flush() Counter.incr(session, "updates") return request
def post(self, *args: Any, **kwargs: Any) -> None: name = self.get_path_argument("name") group = Group.get(self.session, name=name) if not group: return self.notfound() if not user_can_manage_group(self.session, group, self.current_user): return self.forbidden() form = GroupEditForm(self.request.arguments, obj=group) if not form.validate(): return self.render("group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors)) new_name = form.data["groupname"] renamed = group.groupname != new_name if renamed and is_role_user(self.session, group=group): form.groupname.errors.append( "You cannot change the name of service account groups") return self.render("group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors)) if renamed and Group.get(self.session, name=new_name): message = f"A group named '{new_name}' already exists (possibly disabled)" form.groupname.errors.append(message) return self.render("group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors)) group.groupname = new_name group.email_address = form.data["email_address"] group.description = form.data["description"] group.canjoin = form.data["canjoin"] group.auto_expire = form.data["auto_expire"] group.require_clickthru_tojoin = form.data["require_clickthru_tojoin"] Counter.incr(self.session, "updates") self.session.commit() AuditLog.log(self.session, self.current_user.id, "edit_group", "Edited group.", on_group_id=group.id) url = f"/groups/{group.name}" if renamed: url += "?refresh=yes" self.redirect(url)
def enable_service_account(session, actor, service_account, owner): # type: (Session, User, ServiceAccount, Group) -> None """Enables a service account and sets a new owner.""" enable_user(session, service_account.user, actor, preserve_membership=False) add_service_account(session, owner, service_account) AuditLog.log(session, actor.id, "enable_service_account", "Enabled service account.", on_group_id=owner.id, on_user_id=service_account.user_id) Counter.incr(session, "updates") session.commit()
def test_groups_email(groups, session, graph, http_client, base_url): expected_address = "*****@*****.**" sad = groups['sad-team'] sad.email_address = expected_address session.commit() Counter.incr(session, "updates") graph.update_from_db(session) api_url = url(base_url, '/groups/{}'.format(sad.name)) resp = yield http_client.fetch(api_url) body = json.loads(resp.body) assert body["data"]["group"]["contacts"]["email"] == expected_address
def test_groups_email(groups, session, graph, http_client, base_url): # noqa: F811 expected_address = "*****@*****.**" sad = groups["sad-team"] sad.email_address = expected_address session.commit() Counter.incr(session, "updates") graph.update_from_db(session) api_url = url(base_url, "/groups/{}".format(sad.name)) resp = yield http_client.fetch(api_url) body = json.loads(resp.body) assert body["data"]["group"]["contacts"]["email"] == expected_address
def post(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if not user_can_manage_group(self.session, group, self.current_user): return self.forbidden() form = GroupEditForm(self.request.arguments, obj=group) if not form.validate(): return self.render("group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors)) if group.groupname != form.data["groupname"] and is_role_user( self.session, group=group): form.groupname.errors.append( "You cannot change the name of service account groups") return self.render("group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors)) group.groupname = form.data["groupname"] group.email_address = form.data["email_address"] group.description = form.data["description"] group.canjoin = form.data["canjoin"] group.auto_expire = form.data["auto_expire"] group.require_clickthru_tojoin = form.data["require_clickthru_tojoin"] Counter.incr(self.session, "updates") try: self.session.commit() except IntegrityError: self.session.rollback() form.groupname.errors.append("{} already exists".format( form.data["groupname"])) return self.render("group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors)) AuditLog.log(self.session, self.current_user.id, "edit_group", "Edited group.", on_group_id=group.id) return self.redirect("/groups/{}".format(group.name))
def delete_public_key(session, user_id, key_id): """Delete a particular user's public key. Args: session(models.base.session.Session): database session user_id(int): id of user in question key_id(int): id of the user's key we want to delete Throws: KeyNotFound if specified key wasn't found """ pkey = get_public_key(session, user_id, key_id) pkey.delete(session) Counter.incr(session, "updates") session.commit()
def delete_user_password(session, password_name, user_id): # type: (Session, str, int) -> None """Delete the specified UserPassword. Args: session(grouper.models.base.session.Session): database session password_name: the name of the password to delete user_id: the user whose password is being deleted """ p = session.query(UserPassword).filter_by(name=password_name, user_id=user_id).scalar() if not p: raise PasswordDoesNotExist() p.delete(session) Counter.incr(session, "updates") session.commit()
def add_public_key(session, user, public_key_str): """Add a public key for a particular user. Args: session: db session user: User model of user in question public_key_str: public key to add Throws: DuplicateKey if key is already in use PublicKeyParseError if key can't be parsed BadPublicKey if a plugin rejects the key Returns: PublicKey model object representing the key """ pubkey = sshpubkeys.SSHKey(public_key_str, strict=True) try: pubkey.parse() except sshpubkeys.InvalidKeyException as e: raise PublicKeyParseError(str(e)) try: get_plugin_proxy().will_add_public_key(pubkey) except PluginRejectedPublicKey as e: raise BadPublicKey(str(e)) db_pubkey = PublicKey( user=user, public_key=pubkey.keydata.strip(), fingerprint=pubkey.hash_md5().replace("MD5:", ""), fingerprint_sha256=pubkey.hash_sha256().replace("SHA256:", ""), key_size=pubkey.bits, key_type=pubkey.key_type, comment=pubkey.comment, ) try: db_pubkey.add(session) Counter.incr(session, "updates") except IntegrityError: session.rollback() raise DuplicateKey() session.commit() return db_pubkey
def add_public_key(session, user, public_key_str): """Add a public key for a particular user. Args: session: db session user: User model of user in question public_key_str: public key to add Throws: DuplicateKey if key is already in use PublicKeyParseError if key can't be parsed BadPublicKey if a plugin rejects the key Returns: PublicKey model object representing the key """ pubkey = sshpubkeys.SSHKey(public_key_str, strict=True) try: pubkey.parse() except sshpubkeys.InvalidKeyException as e: raise PublicKeyParseError(e.message) try: get_plugin_proxy().will_add_public_key(pubkey) except PluginRejectedPublicKey as e: raise BadPublicKey(e.message) db_pubkey = PublicKey( user=user, public_key=pubkey.keydata.strip(), fingerprint=pubkey.hash_md5().replace(b"MD5:", b""), fingerprint_sha256=pubkey.hash_sha256().replace(b"SHA256:", b""), key_size=pubkey.bits, key_type=pubkey.key_type, comment=pubkey.comment, ) try: db_pubkey.add(session) Counter.incr(session, "updates") except IntegrityError: session.rollback() raise DuplicateKey() session.commit() return db_pubkey
def disable_service_account(session, actor, service_account): # type: (Session, User, ServiceAccount) -> None """Disables a service account and deletes the association with a Group.""" disable_user(session, service_account.user) owner_id = service_account.owner.group.id service_account.owner.delete(session) permissions = session.query(ServiceAccountPermissionMap).filter_by( service_account_id=service_account.id) for permission in permissions: permission.delete(session) AuditLog.log(session, actor.id, "disable_service_account", "Disabled service account.", on_group_id=owner_id, on_user_id=service_account.user_id) Counter.incr(session, "updates") session.commit()
def post(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if not user_can_manage_group(self.session, group, self.current_user): return self.forbidden() form = GroupEditForm(self.request.arguments, obj=group) if not form.validate(): return self.render( "group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors) ) if (group.groupname != form.data["groupname"] and is_service_account(self.session, group=group)): form.groupname.errors.append("You cannot change the name of service account groups") return self.render( "group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors) ) group.groupname = form.data["groupname"] group.description = form.data["description"] group.canjoin = form.data["canjoin"] group.auto_expire = form.data["auto_expire"] Counter.incr(self.session, "updates") try: self.session.commit() except IntegrityError: self.session.rollback() form.groupname.errors.append( "{} already exists".format(form.data["groupname"]) ) return self.render( "group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors) ) AuditLog.log(self.session, self.current_user.id, 'edit_group', 'Edited group.', on_group_id=group.id) return self.redirect("/groups/{}".format(group.name))
def add_new_user_password(session, password_name, password, user_id): # type: (Session, str, str, int) -> None """Add the new user password specified. Args: session(grouper.models.base.session.Session): database session password_name(str): name of the password to be added password(str): the (plaintext) password to be added user_id(int): the id of the user to add this password to """ p = UserPassword(name=password_name, user_id=user_id) p.set_password(password) Counter.incr(session, "updates") p.add(session) try: session.commit() except IntegrityError: raise PasswordAlreadyExists()
def edit_service_account(session, actor, service_account, description, machine_set): # type: (Session, User, ServiceAccount, str, str) -> None """Update the description and machine set of a service account. Raises: PluginRejectedMachineSet: if some plugin rejected the machine set """ if machine_set is not None: _check_machine_set(service_account, machine_set) service_account.description = description service_account.machine_set = machine_set Counter.incr(session, "updates") session.commit() AuditLog.log(session, actor.id, "edit_service_account", "Edited service account.", on_user_id=service_account.user.id)
def test_permissions_aliased_permissions(mocker, session, standard_graph, http_client, base_url): proxy = PluginProxy([PermissionAliasesPlugin()]) mocker.patch('grouper.graph.get_plugin_proxy', return_value=proxy) # Force graph update Counter.incr(session, "updates") standard_graph.update_from_db(session) api_url = url(base_url, '/permissions/ssh') resp = yield http_client.fetch(api_url) body = json.loads(resp.body) permissions = [ (group, p['argument']) for group, g in body['data']['groups'].iteritems() for p in g['permissions'] ] assert ('sad-team', 'owner=sad-team') in permissions
def add_new_user_token(session, user_token): """Add the new user token specified. If user token doesn't contain a secret, create one. Args: session(grouper.models.base.session.Session): database session user_token(grouper.models.user_token.UserToken): token to create Returns: 2-tuple of the created UserToken and the secret """ secret = None if user_token.hashed_secret is None: secret = user_token._set_secret() user_token.add(session) Counter.incr(session, "updates") return user_token, secret
def test_users_aliased_permissions( mocker, session, standard_graph, http_client, base_url # noqa: F811 ): proxy = PluginProxy([PermissionAliasesPlugin()]) mocker.patch("grouper.graph.get_plugin_proxy", return_value=proxy) # Force graph update Counter.incr(session, "updates") standard_graph.update_from_db(session) api_url = url(base_url, "/users/[email protected]") resp = yield http_client.fetch(api_url) body = json.loads(resp.body) perms = [(p["permission"], p["argument"]) for p in body["data"]["permissions"]] assert ("owner", "sad-team") in perms assert ("ssh", "owner=sad-team") in perms assert ("sudo", "sad-team") in perms
def remove_tag_from_public_key(session, public_key, tag): # type: (Session, PublicKey, PublicKeyTag) -> None """Removes the tag from the given public key. Args: session(models.base.session.Session): database session public_key(models.public_key.PublicKey): the public key to be tagged tag(models.public_key_tag.PublicKeyTag): the tag to be removed from the public key Throws: TagNotOnKey if the tag was already assigned to the public key """ mapping = session.query(PublicKeyTagMap).filter_by(tag_id=tag.id, key_id=public_key.id).scalar() if not mapping: raise TagNotOnKey() mapping.delete(session) Counter.incr(session, "updates") session.commit()
def enable_permission_auditing(session, permission_name, actor_user_id): """Set a permission as audited. Args: session(models.base.session.Session): database session permission_name(str): name of permission in question actor_user_id(int): id of user who is enabling auditing """ permission = Permission.get(session, permission_name) if not permission: raise NoSuchPermission(name=permission_name) permission._audited = True AuditLog.log(session, actor_user_id, 'enable_auditing', 'Enabled auditing.', on_permission_id=permission.id) Counter.incr(session, "updates") session.commit()