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 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 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 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 _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 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 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 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 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 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 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()
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 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': 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 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