def convert_existing_opsets(dryrun): """Convert the opsets in db with those defined in convert_mapping, by changing their names.""" logger.debug('Convert existing opsets to new ones') baos = BofhdAuthOpSet(db) name2id = {} for name in opset_config.convert_mapping.keys(): baos.clear() baos.find_by_name(name) name2id[name] = int(baos.op_set_id) if not opset_config.convert_mapping[name]: continue baos.clear() baos.find_by_name(opset_config.convert_mapping[name]) name2id[opset_config.convert_mapping[name]] = int(baos.op_set_id) for src, target in opset_config.convert_mapping.items(): if not target: continue logger.info('Converting opset: %s -> %s', src, target) db.execute(""" UPDATE [:table schema=cerebrum name=auth_role] SET op_set_id=:new_id WHERE op_set_id=:old_id""", { 'old_id': name2id[src], 'new_id': name2id[target]}) if dryrun: db.rollback() logger.info('Rolled back changes') else: db.commit() logger.info('Changes committed')
def list_opset_accounts(self, group, opset_name): """ Return accounts holding a specific permission L{opset_name} on L{group}. This method is meant for answering questions like 'which accounts moderate this group?'. @type group: Cerebrum.Group @param group: A populated group object to list 'moderators' for. @rtype: list @return: A list of dictionaries with keys: ['account_id', 'account_name', 'owner_name', 'email_address', 'group_id', 'group_name', 'description'] See also L{list_opset_groups}. """ assert opset_name in GROUP_AUTH_OPSETS assert hasattr(group, 'entity_id') ac = self.account_class(self.db) ba = BofhdVirtHomeAuth(self.db) aos = BofhdAuthOpSet(self.db) aos.find_by_name(opset_name) tmp = list(ba.get_permission_holders_on_groups( aos.op_set_id, group_id=group.entity_id)) for entry in tmp: ac.clear() ac.find(entry['account_id']) entry['owner_name'] = ac.get_owner_name(self.co.human_full_name) entry['email_address'] = ac.get_email_address() return tmp
def get_groups_moderators(groups): aot = BofhdAuthOpTarget(db) ar = BofhdAuthRole(db) aos = BofhdAuthOpSet(db) co = Factory.get('Constants')(db) en = Factory.get('Entity')(db) for group in groups: group_id = group[0] targets = [] for row in aot.list(target_type = 'group', entity_id = group_id): targets.append(int(row['op_target_id'])) for row in ar.list_owners(targets): aos.clear() aos.find(row['op_set_id']) id = int(row['entity_id']) en.clear() en.find(id) entity_id = int(en.entity_id) en.clear() ent = en.get_subclassed_object(entity_id) if ent.entity_type == co.entity_account: owner = ent.account_name elif ent.entity_type == co.entity_group: owner = ent.group_name else: owner = '#%d' % id group.append(" ".join([str(co.EntityType(ent.entity_type)), owner, aos.name]))
def set_group_owner(self, owner_id, group_id): """ This method will simply set up the Entity L{owner_id} as a C{Group-owner} of group L{group_id}. @type db: Cerebrum.Database.Database @param db: A Cerebrum database object. @type owner_id: int @param owner_id: The C{entity_id} of the owner object. @type group_id: int @param group_id: The C{group_id} of a group object. """ ar = BofhdAuthRole(self.db) aos = BofhdAuthOpSet(self.db) aot = BofhdAuthOpTarget(self.db) # Find or create group operation target try: aot.find( aot.list(entity_id=group_id, target_type=self.co.auth_target_type_group)[0] ['op_target_id']) except IndexError: aot.populate(group_id, self.co.auth_target_type_group) aot.write_db() # Find the 'Group-owner' OpSet to get its entity_id aos.find_by_name('Group-owner') if not len(ar.list(owner_id, aos.op_set_id, aot.op_target_id)): ar.grant_auth(owner_id, aos.op_set_id, aot.op_target_id) return True return False
def list_opset_groups(self, account, opset_name): """ Return groups where L{account} has the specific permission L{opset_name}. This is a complement to the L{list_ownership_accounts). This method is meant for answering questions like 'which groups am I moderating?' @type group: Cerebrum.Account @param group: The account to list 'moderated group' for. @type opset_name: str @param opset_name: The permission to list groups for. @rtype: list @return: A list of dictionaries with keys: ['group_id', 'group_name', 'url', 'description', 'account_id', 'account_name'] """ assert opset_name in GROUP_AUTH_OPSETS assert hasattr(account, 'entity_id') gr = self.group_class(self.db) ba = BofhdVirtHomeAuth(self.db) aos = BofhdAuthOpSet(self.db) aos.find_by_name(opset_name) tmp = list(ba.get_permission_holders_on_groups( aos.op_set_id, account_id=account.entity_id)) for entry in tmp: gr.clear() gr.find(entry['group_id']) entry['url'] = gr.get_contact_info(self.co.virthome_group_url) return tmp
def _get_opset(self, opset): aos = BofhdAuthOpSet(self.db) try: aos.find_by_name(opset) except Errors.NotFoundError: raise CerebrumError("Could not find op set with name %s" % opset) return aos
def access_list_opsets(self, operator): baos = BofhdAuthOpSet(self.db) ret = [] for r in baos.list(): ret.append({'opset': r['name']}) ret.sort(lambda x, y: cmp(x['opset'].lower(), y['opset'].lower())) return ret
def set_group_owner(self, owner_id, group_id): """ This method will simply set up the Entity L{owner_id} as a C{Group-owner} of group L{group_id}. @type db: Cerebrum.Database.Database @param db: A Cerebrum database object. @type owner_id: int @param owner_id: The C{entity_id} of the owner object. @type group_id: int @param group_id: The C{group_id} of a group object. """ ar = BofhdAuthRole(self.db) aos = BofhdAuthOpSet(self.db) aot = BofhdAuthOpTarget(self.db) # Find or create group operation target try: aot.find(aot.list(entity_id=group_id, target_type=self.co.auth_target_type_group )[0]['op_target_id']) except IndexError: aot.populate(group_id, self.co.auth_target_type_group) aot.write_db() # Find the 'Group-owner' OpSet to get its entity_id aos.find_by_name('Group-owner') if not len(ar.list(owner_id, aos.op_set_id, aot.op_target_id)): ar.grant_auth(owner_id, aos.op_set_id, aot.op_target_id) return True return False
def write_db(self): """Write PosixUser instance to database, in addition to the personal file group. As long as L{gid_id} is not set, it gets set to the account's personal file group instead. """ if not self.gid_id: # Create the PosixGroup first, to get its entity_id # TODO: Should we handle that self.pg could not be populated when # we're here? When could gid_id be none without running populate? self.pg.write_db() # We'll need to set this here, as the groups entity_id is # created when we write to the DB. self.gid_id = self.pg.entity_id ret = self.__super.write_db() # Become a member of the group: if not hasattr(self.pg, "entity_id"): self.pg.find(self.gid_id) if not self.pg.has_member(self.entity_id): self.pg.add_member(self.entity_id) # If the dfg is not a personal group we are done now: # TODO: check trait_personal_dfg instead or in addition? if self.account_name != self.pg.group_name: return ret # Set the personal file group trait if not self.pg.get_trait(self.const.trait_personal_dfg): self.pg.populate_trait(self.const.trait_personal_dfg, target_id=self.entity_id) self.pg.write_db() # Register the posixuser as owner of the group, if not already set op_target = BofhdAuthOpTarget(self._db) if not op_target.list(entity_id=self.pg.entity_id, target_type="group"): op_target.populate(self.pg.entity_id, "group") op_target.write_db() op_set = BofhdAuthOpSet(self._db) op_set.find_by_name(cereconf.BOFHD_AUTH_GROUPMODERATOR) role = BofhdAuthRole(self._db) role.grant_auth(self.entity_id, op_set.op_set_id, op_target.op_target_id) # Syncronizing the groups spreads with the users mapping = { int(self.const.spread_uio_nis_user): int(self.const.spread_uio_nis_fg), int(self.const.spread_uio_ad_account): int(self.const.spread_uio_ad_group), int(self.const.spread_ifi_nis_user): int(self.const.spread_ifi_nis_fg), } user_spreads = [int(r["spread"]) for r in self.get_spread()] group_spreads = [int(r["spread"]) for r in self.pg.get_spread()] for uspr, gspr in mapping.iteritems(): if uspr in user_spreads: if gspr not in group_spreads: self.pg.add_spread(gspr) elif gspr in group_spreads: self.pg.delete_spread(gspr) return ret
def _group_make_owner(self, owner, target): op_set = BofhdAuthOpSet(self.db) op_set.find_by_name(cereconf.BOFHD_AUTH_GROUPMODERATOR) op_target = BofhdAuthOpTarget(self.db) op_target.populate(target.entity_id, 'group') op_target.write_db() role = BofhdAuthRole(self.db) role.grant_auth(owner.entity_id, op_set.op_set_id, op_target.op_target_id)
def _set_owner_of_group(self, group): op_target = BofhdAuthOpTarget(self._db) if not op_target.list(entity_id=group.entity_id, target_type='group'): op_target.populate(group.entity_id, 'group') op_target.write_db() op_set = BofhdAuthOpSet(self._db) op_set.find_by_name(cereconf.BOFHD_AUTH_GROUPMODERATOR) role = BofhdAuthRole(self._db) role.grant_auth(self.entity_id, op_set.op_set_id, op_target.op_target_id)
def list_alterable_entities(self, operator, target_type): """Find entities of `target_type` that `operator` can moderate. 'Moderate' in this context is equivalent with `auth_operation_set` defined in `cereconf.BOFHD_AUTH_GROUPMODERATOR`. :param int operator: The account on behalf of which the query is to be executed. :param str target_type: The kind of entities for which permissions are checked. The only permissible values are 'group', 'disk', 'host' and 'maildom'. """ legal_target_types = ('group', 'disk', 'host', 'maildom') if target_type not in legal_target_types: raise ValueError("Illegal target_type <%s>" % target_type) operator_id = int(operator) opset = BofhdAuthOpSet(self._db) opset.find_by_name(cereconf.BOFHD_AUTH_GROUPMODERATOR) sql = """ SELECT aot.entity_id FROM [:table schema=cerebrum name=auth_op_target] aot, [:table schema=cerebrum name=auth_role] ar WHERE ( ar.entity_id = :operator_id OR -- do NOT replace with EXISTS, it's much more expensive ar.entity_id IN ( SELECT gm.group_id FROM [:table schema=cerebrum name=group_member] gm WHERE gm.member_id = :operator_id )) AND ar.op_target_id = aot.op_target_id AND aot.target_type = :target_type AND ar.op_set_id = :op_set_id """ return self.query( sql, { "operator_id": operator_id, "target_type": target_type, "op_set_id": opset.op_set_id })
def revoke_group_auth(self, account, opset_name, group): """ Removes L{account_id} access type L{opset_name} over group L{group_id}. This can be used to remove admin and moderator access to groups. @type account: self.account_class @param account: The account that should be granted access @type opset_name: str @param opset_name: The name of the operation set (type of access) @type group: self.group_class @param group: The group that L{account} should be given access to @rtype: bool @return: True if access was revoked, False if access didn't exist. """ assert opset_name in GROUP_AUTH_OPSETS assert hasattr(account, 'entity_id') assert hasattr(group, 'entity_id') ar = BofhdAuthRole(self.db) aos = BofhdAuthOpSet(self.db) aos.find_by_name(opset_name) aot = self.find_or_create_op_target(group.entity_id, self.co.auth_target_type_group) assert account.np_type in (self.co.fedaccount_type, self.co.account_program) assert aot.target_type == self.co.auth_target_type_group roles = list(ar.list(account.entity_id, aos.op_set_id, aot.op_target_id)) if len(roles) == 0: return False # No permissions to remove ar.revoke_auth(account.entity_id, aos.op_set_id, aot.op_target_id) # If that was the last permission for this op_target, kill op_target if len(list(ar.list(op_target_id=aot.op_target_id))) == 0: aot.delete() return True # Permissions removed
def get_groups_moderators(groups): aot = BofhdAuthOpTarget(db) ar = BofhdAuthRole(db) aos = BofhdAuthOpSet(db) co = Factory.get('Constants')(db) en = Factory.get('Entity')(db) for group in groups: group_id = group[0] targets = [] for row in aot.list(target_type='group', entity_id=group_id): targets.append(int(row['op_target_id'])) for row in ar.list_owners(targets): aos.clear() aos.find(row['op_set_id']) id = int(row['entity_id']) en.clear() en.find(id) entity_id = int(en.entity_id) en.clear() ent = en.get_subclassed_object(entity_id) if ent.entity_type == co.entity_account: owner = ent.account_name elif ent.entity_type == co.entity_group: owner = ent.group_name else: owner = '#%d' % id group.append(" ".join( [str(co.EntityType(ent.entity_type)), owner, aos.name]))
def _list_access(self, target_type, target_name=None, empty_result="None"): target_id, target_type, target_auth = self._get_access_id( target_type, target_name) ret = [] ar = BofhdAuthRole(self.db) aos = BofhdAuthOpSet(self.db) for r in self._get_auth_op_target(target_id, target_type, any_attr=True): attr = str(r['attr'] or '') for r2 in ar.list(op_target_id=r['op_target_id']): aos.clear() aos.find(r2['op_set_id']) ety = self._get_entity(ident=r2['entity_id']) ret.append({ 'opset': aos.name, 'attr': attr, 'type': six.text_type(self.const.EntityType(ety.entity_type)), 'name': self._get_name_from_object(ety), }) ret.sort(lambda a, b: (cmp(a['opset'], b['opset']) or cmp(a['name'], b['name']))) return ret or empty_result
def convert_opsets(db, opsets): """ Changes all granted opsets from `opsets.convert_mapping`. For each mapped opset (old_opset -> new_opset) in `convert_mapping`, any granted access to the old_opset is changed to the new_opset. This is needed when existing opsets are refactored (e.g. split, combined or just renamed). """ logger.debug('Convert existing opsets to new ones') convert_mapping = getattr(opsets, 'convert_mapping', dict()) if not convert_mapping: raise OpsetConfigError("No opset mappings defined in convert_mapping!") baos = BofhdAuthOpSet(db) name2id = {} for name in convert_mapping.keys(): baos.clear() baos.find_by_name(name) name2id[name] = int(baos.op_set_id) if not convert_mapping[name]: continue baos.clear() baos.find_by_name(convert_mapping[name]) name2id[convert_mapping[name]] = int(baos.op_set_id) for src, target in convert_mapping.items(): if not target: continue logger.info('Converting opset: %s -> %s', src, target) db.execute( """ UPDATE [:table schema=cerebrum name=auth_role] SET op_set_id=:new_id WHERE op_set_id=:old_id""", { 'old_id': name2id[src], 'new_id': name2id[target] })
def grant_group_auth(self, account, opset_name, group): """ Grants L{entity_id} access type L{opset_name} over group L{group_id}. This can be used to give admin and moderator access to groups. @type account: self.account_class @param account: The account that should be granted access @type opset_name: str @param opset_name: The name of the operation set (type of access) @type group: self.group_class @param group: The group that L{account} should be given access to @rtype: bool @return: True if access was granted, False if access already exists """ assert opset_name in GROUP_AUTH_OPSETS assert hasattr(account, 'entity_id') assert hasattr(group, 'entity_id') ar = BofhdAuthRole(self.db) aos = BofhdAuthOpSet(self.db) aot = self.find_or_create_op_target(group.entity_id, self.co.auth_target_type_group) aos.find_by_name(opset_name) assert account.np_type in (self.co.fedaccount_type, self.co.account_program) assert hasattr(aot, 'op_target_id') # Must be populated roles = list(ar.list(account.entity_id, aos.op_set_id, aot.op_target_id)) if len(roles) == 0: ar.grant_auth(account.entity_id, aos.op_set_id, aot.op_target_id) return True # Access granted return False # Already had access
def group_info(self, operator, groupname): grp = self._get_group(groupname) co = self.const ret = [self._entity_info(grp), ] # find owners aot = BofhdAuthOpTarget(self.db) targets = [] for row in aot.list(target_type='group', entity_id=grp.entity_id): targets.append(int(row['op_target_id'])) ar = BofhdAuthRole(self.db) aos = BofhdAuthOpSet(self.db) for row in ar.list_owners(targets): aos.clear() aos.find(row['op_set_id']) id = int(row['entity_id']) en = self._get_entity(ident=id) if en.entity_type == co.entity_account: owner = en.account_name elif en.entity_type == co.entity_group: owner = en.group_name else: owner = '#%d' % id ret.append({ 'owner_type': text_type(co.EntityType(en.entity_type)), 'owner': owner, 'opset': aos.name, }) # Count group members of different types members = list(grp.search_members(group_id=grp.entity_id)) tmp = {} for ret_pfix, entity_type in ( ('c_group', int(co.entity_group)), ('c_account', int(co.entity_account))): tmp[ret_pfix] = len([x for x in members if int(x["member_type"]) == entity_type]) ret.append(tmp) return ret
def grant_auth(en, gr, opset): """Grant authorization to a group. :type en: <Cerebrum.Entity.Entity> :param en: The entity to grant auth to. :type gr: <Cerebrum.Group.Group> :param gr: The group to grant auth on. :type opset: str :param opset: The OpSet to be granted.""" # TODO: ._db? 'group' to op_target.populate ok? should be derived from # gr, but that means we'll need to do Factory.get in here... :( # TODO: Can this be generalized and moved to utils?? from Cerebrum.modules.bofhd.auth import BofhdAuthOpSet, \ BofhdAuthOpTarget, BofhdAuthRole op_set = BofhdAuthOpSet(en._db) op_set.find_by_name(opset) op_target = BofhdAuthOpTarget(en._db) op_target.populate(gr.entity_id, 'group') op_target.write_db() role = BofhdAuthRole(en._db) role.grant_auth(en.entity_id, op_set.op_set_id, op_target.op_target_id)
def convert_opsets(db, opsets): """ Changes all granted opsets from `opsets.convert_mapping`. For each mapped opset (old_opset -> new_opset) in `convert_mapping`, any granted access to the old_opset is changed to the new_opset. This is needed when existing opsets are refactored (e.g. split, combined or just renamed). """ logger.debug('Convert existing opsets to new ones') convert_mapping = getattr(opsets, 'convert_mapping', dict()) if not convert_mapping: raise OpsetConfigError("No opset mappings defined in convert_mapping!") baos = BofhdAuthOpSet(db) name2id = {} for name in convert_mapping.keys(): baos.clear() baos.find_by_name(name) name2id[name] = int(baos.op_set_id) if not convert_mapping[name]: continue baos.clear() baos.find_by_name(convert_mapping[name]) name2id[convert_mapping[name]] = int(baos.op_set_id) for src, target in convert_mapping.items(): if not target: continue logger.info('Converting opset: %s -> %s', src, target) db.execute( """ UPDATE [:table schema=cerebrum name=auth_role] SET op_set_id=:new_id WHERE op_set_id=:old_id""", {'old_id': name2id[src], 'new_id': name2id[target]})
def group_info(self, operator, groupname): grp = self._get_group(groupname) co = self.const ret = [ self._entity_info(grp) ] # find owners aot = BofhdAuthOpTarget(self.db) targets = [] for row in aot.list(target_type='group', entity_id=grp.entity_id): targets.append(int(row['op_target_id'])) ar = BofhdAuthRole(self.db) aos = BofhdAuthOpSet(self.db) for row in ar.list_owners(targets): aos.clear() aos.find(row['op_set_id']) id = int(row['entity_id']) en = self._get_entity(ident=id) if en.entity_type == co.entity_account: owner = en.account_name elif en.entity_type == co.entity_group: owner = en.group_name else: owner = '#%d' % id ret.append({'owner_type': str(co.EntityType(en.entity_type)), 'owner': owner, 'opset': aos.name}) # Count group members of different types members = list(grp.search_members(group_id=grp.entity_id)) tmp = {} for ret_pfix, entity_type in ( ('c_group', int(self.const.entity_group)), ('c_account', int(self.const.entity_account))): tmp[ret_pfix] = len([x for x in members if int(x["member_type"]) == entity_type]) ret.append(tmp) return ret
def access_show_opset(self, operator, opset=None): baos = BofhdAuthOpSet(self.db) try: baos.find_by_name(opset) except Errors.NotFoundError: raise CerebrumError("Unknown operation set: '{}'".format(opset)) ret = [] for r in baos.list_operations(): entry = { 'op': six.text_type(self.const.AuthRoleOp(r['op_code'])), 'desc': self.const.AuthRoleOp(r['op_code']).description, } attrs = [] for r2 in baos.list_operation_attrs(r['op_id']): attrs += [r2['attr']] if not attrs: attrs = [""] for a in attrs: entry_with_attr = entry.copy() entry_with_attr['attr'] = a ret += [entry_with_attr] ret.sort(lambda x, y: (cmp(x['op'], y['op']) or cmp(x['attr'], y['attr']))) return ret
def clean_opsets(db, opsets): """ Remove opsets not defined in `opsets.operation_sets`. """ operation_sets = getattr(opsets, 'operation_sets', dict()) if not operation_sets: raise OpsetConfigError("No opsets defined in operation_sets!") co = Factory.get('Constants')(db) baos = BofhdAuthOpSet(db) bar = BofhdAuthRole(db) for op_set_id, name in baos.list(): if name not in operation_sets.keys(): logger.info('Opset %s is no longer defined', name) baos.clear() baos.find(op_set_id) for op_code, op_id, _ in baos.list_operations(): logger.info( 'Deleting operation for opset %s: op_code=%s op_id=%s', baos.name, six.text_type(co.AuthRoleOp(op_code)), op_id) baos.del_operation(op_code, op_id) for role in bar.list(op_set_id=op_set_id): logger.info('Revoking %s for %s on %s', baos.name, role['entity_id'], role['op_target_id']) bar.revoke_auth(**role) logger.info('Deleting opset %s', name) baos.delete()
def create_required_opsets(operation_sets, db): """Make sure the necessary auth op sets are in the db. If such an opset already exists, force the specified set of auth_operation. """ const = Factory.get("Constants")() baos = BofhdAuthOpSet(db) for auth_opset in operation_sets: baos.clear() try: baos.find_by_name(auth_opset) except Errors.NotFoundError: baos.populate(auth_opset) baos.write_db() requested_opcodes = set(int(const.human2constant(x, const.AuthRoleOp)) for x in operation_sets[auth_opset]) existing_opcodes = set(int(row["op_code"]) for row in baos.list_operations()) for op_code in requested_opcodes.difference(existing_opcodes): logger.debug("Adding operation opcode=%s (code_str=%s) to opset %s " "(opset_id=%s)", op_code, str(const.AuthRoleOp(op_code)), baos.name, baos.op_set_id) baos.add_operation(op_code) for op_code in existing_opcodes.difference(requested_opcodes): logger.debug("Deleting operation opcode=%s (code_str=%s) from opset %s " "(opset_id=%s)", op_code, str(const.AuthRoleOp(op_code)), baos.name, baos.op_set_id) baos.del_operation(op_code) baos.write_db()
def write_db(self): """Write PosixUser instance to database, in addition to the personal file group. As long as L{gid_id} is not set, it gets set to the account's personal file group instead. """ if not self.gid_id: # Create the PosixGroup first, to get its entity_id # TODO: Should we handle that self.pg could not be populated when # we're here? When could gid_id be none without running populate? self.pg.write_db() # We'll need to set this here, as the groups entity_id is # created when we write to the DB. self.gid_id = self.pg.entity_id ret = self.__super.write_db() # Become a member of the group: if not hasattr(self.pg, 'entity_id'): self.pg.find(self.gid_id) if not self.pg.has_member(self.entity_id): self.pg.add_member(self.entity_id) # If the dfg is not a personal group we are done now: # TODO: check trait_personal_dfg instead or in addition? if self.account_name != self.pg.group_name: return ret # Set the personal file group trait if not self.pg.get_trait(self.const.trait_personal_dfg): self.pg.populate_trait(self.const.trait_personal_dfg, target_id=self.entity_id) self.pg.write_db() # Register the posixuser as owner of the group, if not already set op_target = BofhdAuthOpTarget(self._db) if not op_target.list(entity_id=self.pg.entity_id, target_type='group'): op_target.populate(self.pg.entity_id, 'group') op_target.write_db() op_set = BofhdAuthOpSet(self._db) op_set.find_by_name(cereconf.BOFHD_AUTH_GROUPMODERATOR) role = BofhdAuthRole(self._db) role.grant_auth(self.entity_id, op_set.op_set_id, op_target.op_target_id) # Syncronizing the groups spreads with the users mapping = { int(self.const.spread_uio_nis_user): int(self.const.spread_uio_nis_fg), int(self.const.spread_uio_ad_account): int(self.const.spread_uio_ad_group), int(self.const.spread_ifi_nis_user): int(self.const.spread_ifi_nis_fg) } user_spreads = [int(r['spread']) for r in self.get_spread()] group_spreads = [int(r['spread']) for r in self.pg.get_spread()] for uspr, gspr in mapping.iteritems(): if uspr in user_spreads: if gspr not in group_spreads: self.pg.add_spread(gspr) elif gspr in group_spreads: self.pg.delete_spread(gspr) return ret
def fix_opset(db, name, contents): """ Update a single opset. Creates the opset name if it doesn't exist, and then syncs the operations/permissions in `contents` to the Cerebrum database. """ logger.debug('Checking opset %s' % name) co = Factory.get('Constants')(db) baos = BofhdAuthOpSet(db) baos.clear() try: baos.find_by_name(name) except Errors.NotFoundError: baos.populate(name) baos.write_db() logger.info('OpSet %s unknown, created it', name) current_operations = dict([(int(row['op_code']), int(row['op_id'])) for row in baos.list_operations()]) for k in contents.keys(): op_code = co.AuthRoleOp(k) try: int(op_code) except Errors.NotFoundError: logger.error("Operation %s not defined" % k) continue current_op_id = current_operations.get(int(op_code), None) if current_op_id is None: current_op_id = baos.add_operation(op_code) logger.info('OpSet %s got new operation %s', name, k) else: # already there del current_operations[int(op_code)] current_attrs = [row['attr'] for row in baos.list_operation_attrs(current_op_id)] for a in contents[k].get('attrs', []): if a not in current_attrs: baos.add_op_attrs(current_op_id, a) logger.info("Add attr for %s:%s: %s", name, k, a) else: current_attrs.remove(a) for a in current_attrs: baos.del_op_attrs(current_op_id, a) logger.info("Remove attr for %s:%s: %s", name, k, a) for op in current_operations: # TBD: In theory this should be op_id, should # the DB have a unique constraint? baos.del_operation(op, current_operations[op]) logger.info('OpSet %s had unwanted operation %s, removed it', name, co.AuthRoleOp(op)) baos.write_db()
def access_list(self, operator, owner, target_type=None): """ List everything an account or group can operate on. Only direct ownership is reported: the entities an account can access due to group memberships will not be listed. This does not include unpersonal users owned by groups. :param operator: operator in bofh session :param owner: str name of owner object :param target_type: the type of the target :return: List of everything an account or group can operate on """ ar = BofhdAuthRole(self.db) aot = BofhdAuthOpTarget(self.db) aos = BofhdAuthOpSet(self.db) co = self.const owner_id = self.util.get_target(owner, default_lookup="group", restrict_to=[]).entity_id ret = [] for role in ar.list(owner_id): aos.clear() aos.find(role['op_set_id']) for r in aot.list(target_id=role['op_target_id']): if target_type is not None and r['target_type'] != target_type: continue if r['entity_id'] is None: target_name = "N/A" elif r['target_type'] == co.auth_target_type_maildomain: # FIXME: EmailDomain is not an Entity. ed = Email.EmailDomain(self.db) try: ed.find(r['entity_id']) except (Errors.NotFoundError, ValueError): self.logger.warn("Non-existing entity (e-mail domain) " "in auth_op_target {}:{:d}".format( r['target_type'], r['entity_id'])) continue target_name = ed.email_domain_name elif r['target_type'] == co.auth_target_type_ou: ou = self.OU_class(self.db) try: ou.find(r['entity_id']) except (Errors.NotFoundError, ValueError): self.logger.warn("Non-existing entity (ou) in " "auth_op_target %s:%d" % (r['target_type'], r['entity_id'])) continue target_name = "%02d%02d%02d (%s)" % ( ou.fakultet, ou.institutt, ou.avdeling, ou.short_name) elif r['target_type'] == co.auth_target_type_dns: s = Subnet(self.db) # TODO: should Subnet.find() support ints as input? try: s.find('entity_id:%s' % r['entity_id']) except (Errors.NotFoundError, ValueError, SubnetError): self.logger.warn("Non-existing entity (subnet) in " "auth_op_target %s:%d" % (r['target_type'], r['entity_id'])) continue target_name = "%s/%s" % (s.subnet_ip, s.subnet_mask) else: try: ety = self._get_entity(ident=r['entity_id']) target_name = self._get_name_from_object(ety) except (Errors.NotFoundError, ValueError): self.logger.warn("Non-existing entity in " "auth_op_target %s:%d" % (r['target_type'], r['entity_id'])) continue ret.append({ 'opset': aos.name, 'target_type': r['target_type'], 'target': target_name, 'attr': r['attr'] or "", }) ret.sort(lambda a, b: (cmp(a['target_type'], b['target_type']) or cmp( a['target'], b['target']))) return ret
def fix_opset(db, name, contents): """ Update a single opset. Creates the opset name if it doesn't exist, and then syncs the operations/permissions in `contents` to the Cerebrum database. """ logger.debug('Checking opset %s' % name) co = Factory.get('Constants')(db) baos = BofhdAuthOpSet(db) baos.clear() try: baos.find_by_name(name) except Errors.NotFoundError: baos.populate(name) baos.write_db() logger.info('OpSet %s unknown, created it', name) current_operations = dict([(int(row['op_code']), int(row['op_id'])) for row in baos.list_operations()]) for k in contents.keys(): op_code = co.AuthRoleOp(k) try: int(op_code) except Errors.NotFoundError: logger.error("Operation %s not defined" % k) continue current_op_id = current_operations.get(int(op_code), None) if current_op_id is None: current_op_id = baos.add_operation(op_code) logger.info('OpSet %s got new operation %s', name, k) else: # already there del current_operations[int(op_code)] current_attrs = [ row['attr'] for row in baos.list_operation_attrs(current_op_id) ] for a in contents[k].get('attrs', []): if a not in current_attrs: baos.add_op_attrs(current_op_id, a) logger.info("Add attr for %s:%s: %s", name, k, a) else: current_attrs.remove(a) for a in current_attrs: baos.del_op_attrs(current_op_id, a) logger.info("Remove attr for %s:%s: %s", name, k, a) for op in current_operations: # TBD: In theory this should be op_id, should # the DB have a unique constraint? baos.del_operation(op, current_operations[op]) logger.info('OpSet %s had unwanted operation %s, removed it', name, co.AuthRoleOp(op)) baos.write_db()
def create_required_opsets(operation_sets, db): """Make sure the necessary auth op sets are in the db. If such an opset already exists, force the specified set of auth_operation. """ const = Factory.get("Constants")() baos = BofhdAuthOpSet(db) for auth_opset in operation_sets: baos.clear() try: baos.find_by_name(auth_opset) except Errors.NotFoundError: baos.populate(auth_opset) baos.write_db() requested_opcodes = set( int(const.human2constant(x, const.AuthRoleOp)) for x in operation_sets[auth_opset]) existing_opcodes = set( int(row["op_code"]) for row in baos.list_operations()) for op_code in requested_opcodes.difference(existing_opcodes): logger.debug( "Adding operation opcode=%s (code_str=%s) to opset %s " "(opset_id=%s)", op_code, str(const.AuthRoleOp(op_code)), baos.name, baos.op_set_id) baos.add_operation(op_code) for op_code in existing_opcodes.difference(requested_opcodes): logger.debug( "Deleting operation opcode=%s (code_str=%s) from opset %s " "(opset_id=%s)", op_code, str(const.AuthRoleOp(op_code)), baos.name, baos.op_set_id) baos.del_operation(op_code) baos.write_db()
import cereconf from Cerebrum.Utils import Factory from Cerebrum import Errors from Cerebrum.modules.bofhd.auth import BofhdAuthOpSet, \ BofhdAuthOpTarget, BofhdAuthRole # Initialize logger logger = Factory.get_logger('cronjob') # Initialize database connections db = Factory.get('Database')() ac = Factory.get('Account')(db) pe = Factory.get('Person')(db) gr = Factory.get('Group')(db) baos = BofhdAuthOpSet(db) bar = BofhdAuthRole(db) baot = BofhdAuthOpTarget(db) db.cl_init(change_program="update_affiliation_groups.py") def usage(exitcode=0): print """Usage: %s [Options] Update group memberships for primary accounts based on affiliations. Options: -l, --list List affiliations. -d, --dryrun Don't commit changes to Cerebrum db.
def fix_opset(name, contents): """Fix an operation set by giving it the operations defined in operation_sets, and removing other operations that shouldn't be there. If the opset doesn't exist, it is first created.""" logger.debug('Checking opset %s' % name) baos = BofhdAuthOpSet(db) baos.clear() try: baos.find_by_name(name) except Errors.NotFoundError: baos.populate(name) baos.write_db() logger.info('OpSet %s unknown, created it', name) current_operations = dict([(int(row['op_code']), int(row['op_id'])) for row in baos.list_operations()]) for k in contents.keys(): op_code = co.AuthRoleOp(k) try: int(op_code) except Errors.NotFoundError: logger.error("Operation %s not defined" % k) continue current_op_id = current_operations.get(int(op_code), None) if current_op_id is None: current_op_id = baos.add_operation(op_code) logger.info('OpSet %s got new operation %s', name, k) else: # already there del current_operations[int(op_code)] current_attrs = [row['attr'] for row in baos.list_operation_attrs(current_op_id)] for a in contents[k].get('attrs', []): if a not in current_attrs: baos.add_op_attrs(current_op_id, a) logger.info("Add attr for %s:%s: %s", name, k, a) else: current_attrs.remove(a) for a in current_attrs: baos.del_op_attrs(current_op_id, a) logger.info("Remove attr for %s:%s: %s", name, k, a) for op in current_operations: #TBD: In theory this should be op_id, should # the DB have a unique constraint? baos.del_operation(op, current_operations[op]) logger.info('OpSet %s had unwanted operation %s, removed it', name, co.AuthRoleOp(op)) baos.write_db()