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 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 _get_auth_op_target(self, entity_id, target_type, attr=None, any_attr=False, create=False): """Return auth_op_target(s) associated with (entity_id, target_type, attr). If any_attr is false, return one op_target_id or None. If any_attr is true, return list of matching db_row objects. If create is true, create a new op_target if no matching row is found.""" if any_attr: op_targets = [] assert attr is None and create is False else: op_targets = None aot = BofhdAuthOpTarget(self.db) for r in aot.list(entity_id=entity_id, target_type=target_type, attr=attr): if attr is None and not any_attr and r['attr']: continue if any_attr: op_targets.append(r) else: # There may be more than one matching op_target, but # we don't care which one we use -- we will make sure # not to make duplicates ourselves. op_targets = int(r['op_target_id']) if op_targets or not create: return op_targets # No op_target found, make a new one. aot.populate(entity_id, target_type, attr) aot.write_db() return aot.op_target_id
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 delete(self, perform_checks=True): if perform_checks: if self.has_adresses_in_use(): raise SubnetError( "Subnet '%s/%s' cannot be deleted; it has addresses in use" % (self.subnet_ip, self.subnet_mask)) # Revoke BofhdAuthRoles associated with subnet baot = BofhdAuthOpTarget(self._db) bar = BofhdAuthRole(self._db) targets = [x['op_target_id'] for x in baot.list(entity_id=self.entity_id)] if targets: for target in targets: for x in bar.list(op_target_id=target): bar.revoke_auth(*x) bar.commit() # Remove BofhdAuthOpTarget associated with subnet for x in targets: baot.clear() try: baot.find(x) baot.delete() baot.commit() except NotFoundError: pass self._db.log_change(self.entity_id, self.const.subnet_delete, None) if self.__in_db: self.execute(""" DELETE FROM [:table schema=cerebrum name=dns_subnet] WHERE entity_id=:e_id""", {'e_id': self.entity_id}) self.__super.delete()
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 _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 remove_permissions_on_target(entity_id, db): """Remove all permissions GRANTED ON entity_id. remote_target_permissions() removes permissions held by entity_id. This function removes permissions held by other on entity_id. Cf bofhd_virthome_cmds.py:__remove_auth_target. """ ar = BofhdAuthRole(db) aot = BofhdAuthOpTarget(db) for r in aot.list(entity_id=entity_id): aot.clear() aot.find(r['op_target_id']) # We remove all auth_role entries pointing to this entity_id # first. for role in ar.list(op_target_id=r["op_target_id"]): ar.revoke_auth(role['entity_id'], role['op_set_id'], r['op_target_id']) aot.delete()
def remove_permissions_on_target(entity_id, db): """Remove all permissions GRANTED ON entity_id. remote_target_permissions() removes permissions held by entity_id. This function removes permissions held by other on entity_id. Cf bofhd_virthome_cmds.py:__remove_auth_target. """ ar = BofhdAuthRole(db) aot = BofhdAuthOpTarget(db) for r in aot.list(entity_id=entity_id): aot.clear() aot.find(r['op_target_id']) # We remove all auth_role entries pointing to this entity_id # first. for role in ar.list(op_target_id=r["op_target_id"]): ar.revoke_auth(role['entity_id'], role['op_set_id'], r['op_target_id']) aot.delete()
def find_or_create_op_target(self, entity_id, target_type): """ Finds an op-target of type L{target_type} that points to L{entity_id}. If no targets exist, one will be created. """ aot = BofhdAuthOpTarget(self.db) op_targets = [t for t in aot.list(entity_id=entity_id, target_type=target_type)] # No target exists, create one if not op_targets: aot.populate(entity_id, target_type) aot.write_db() return aot assert len(op_targets) == 1 # This method will never create more than one assert op_targets[0]['attr'] is None # ... and never populates attr # Target exists, return it aot.find(op_targets[0]['op_target_id']) return aot
def find_or_create_op_target(self, entity_id, target_type): """ Finds an op-target of type L{target_type} that points to L{entity_id}. If no targets exist, one will be created. """ aot = BofhdAuthOpTarget(self.db) op_targets = [t for t in aot.list(entity_id=entity_id, target_type=target_type)] # No target exists, create one if not op_targets: aot.populate(entity_id, target_type) aot.write_db() return aot assert len(op_targets) == 1 # This method will never create more than one assert op_targets[0]['attr'] is None # ... and never populates attr # Target exists, return it aot.find(op_targets[0]['op_target_id']) return aot
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 remove_auth_targets(self, entity_id, target_type=None): """ This method will remove authorization targets of type L{target_type} that points to the L{entity_id}. If L{target_type} is None, all targets regardless of type will be removed. @type entity_id: int @param entity_id: The entity_id of an object. @type target_type: str @param target_type: The target type of the authorization target """ ar = BofhdAuthRole(self.db) aot = BofhdAuthOpTarget(self.db) for target in aot.list(entity_id=entity_id, target_type=target_type): aot.clear() aot.find(target['op_target_id']) # Before the target is removed, we must remove all roles that # grants access to the target. for role in ar.list(op_target_id=target["op_target_id"]): ar.revoke_auth(role['entity_id'], role['op_set_id'], target['op_target_id']) aot.delete()
def remove_auth_targets(self, entity_id, target_type=None): """ This method will remove authorization targets of type L{target_type} that points to the L{entity_id}. If L{target_type} is None, all targets regardless of type will be removed. @type entity_id: int @param entity_id: The entity_id of an object. @type target_type: str @param target_type: The target type of the authorization target """ ar = BofhdAuthRole(self.db) aot = BofhdAuthOpTarget(self.db) for target in aot.list(entity_id=entity_id, target_type=target_type): aot.clear() aot.find(target['op_target_id']) # Before the target is removed, we must remove all roles that # grants access to the target. for role in ar.list(op_target_id=target["op_target_id"]): ar.revoke_auth(role['entity_id'], role['op_set_id'], target['op_target_id']) aot.delete()
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_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 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