Пример #1
0
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()
Пример #2
0
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]))            
Пример #3
0
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')
Пример #4
0
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()
Пример #5
0
 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
Пример #6
0
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]))
Пример #7
0
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()
Пример #8
0
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()
Пример #9
0
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()
Пример #10
0
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()
Пример #11
0
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()
Пример #12
0
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]
            })
Пример #13
0
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]})
Пример #14
0
    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
Пример #15
0
    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
Пример #16
0
    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