Пример #1
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')
Пример #2
0
    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
Пример #3
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]))            
Пример #4
0
    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
Пример #5
0
    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
Пример #6
0
 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
Пример #7
0
    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
Пример #8
0
    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
Пример #9
0
 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
Пример #10
0
    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
Пример #11
0
    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
Пример #12
0
 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)
Пример #13
0
 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)
Пример #14
0
    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
            })
Пример #15
0
    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
Пример #16
0
    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
Пример #17
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]))
Пример #18
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
Пример #19
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]
            })
Пример #20
0
    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
Пример #21
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
Пример #22
0
    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
Пример #23
0
    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)
Пример #24
0
    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)
Пример #25
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]})
Пример #26
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
Пример #27
0
 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
Пример #28
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()
Пример #29
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()
Пример #30
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()
Пример #31
0
    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
Пример #32
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()
Пример #33
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
Пример #34
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()
Пример #35
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()
Пример #36
0
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.
Пример #37
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()