def __get_template(self, selection):
        u""" Get a template.

        :param str selection:
            If numerical string, get the n-th template.
            Else match it according to the help text.

        :return list,dict: A template dict or list of template descriptions.

        """
        tpl_options = self.__list_password_print_options()

        # Numeric selection
        try:
            return tpl_options[int(selection) - 1]
        except IndexError:
            raise CerebrumError(
                u"Invalid template number %d, must be in range 1-%d" %
                (selection, len(tpl_options)))
        except ValueError:
            # int() failed
            pass

        # Text selection
        try:
            lang, ttype = selection.split(':', 1)
            for tpl in tpl_options:
                if tpl.get('lang') == lang and tpl.get('type') == ttype:
                    return tpl
            raise CerebrumError(u"No template %r in language %r" %
                                (lang, ttype))
        except ValueError:
            # unpacking of selection.split() failed
            pass
        raise CerebrumError("Invalid template %r" % selection)
Esempio n. 2
0
    def _split_email_address(self, addr, with_checks=True):
        """Split an e-mail address into local part and domain.

        Additionally, perform certain basic checks to ensure that the address
        looks sane.

        @type addr: basestring
        @param addr:
          E-mail address to split, spelled as 'foo@domain'.

        @type with_checks: bool
        @param with_checks:
          Controls whether to perform local part checks on the
          address. Occasionally we may want to sidestep this (e.g. when
          *removing* things from the database).

        @rtype: tuple of (basestring, basestring)
        @return:
          A pair, local part and domain extracted from the L{addr}.
        """
        from Cerebrum.modules import Email
        if addr.count('@') == 0:
            raise CerebrumError("E-mail address (%s) must include domain" %
                                addr)
        lp, dom = addr.split('@')
        if addr != addr.lower() and \
           dom not in cereconf.LDAP['rewrite_email_domain']:
            raise CerebrumError(
                "E-mail address (%s) can't contain upper case letters" % addr)
        if not with_checks:
            return lp, dom
        ea = Email.EmailAddress(self.db)
        if not ea.validate_localpart(lp):
            raise CerebrumError("Invalid localpart '%s'" % lp)
        return lp, dom
 def ephorte_remove_role(self, operator,
                         person_id, role, sko, arkivdel, journalenhet):
     if not self.ba.can_remove_ephorte_role(operator.get_entity_id()):
         raise PermissionDenied("Currently limited to ephorte admins")
     try:
         person = self.util.get_target(person_id, restrict_to=['Person'])
     except Errors.TooManyRowsError:
         raise CerebrumError("Unexpectedly found more than one person")
     ou = self._get_ou(stedkode=sko)
     arkivdel = self._get_arkivdel(arkivdel)
     journalenhet = self._get_journalenhet(journalenhet)
     role = self._get_role_type(role)
     # Check that the person has the given role.
     if not self.ephorte_role.get_role(
             person.entity_id,
             role,
             ou.entity_id,
             arkivdel,
             journalenhet):
         raise CerebrumError("Person has no such role")
     # Check if role is a standard role
     _list_roles = self.ephorte_role.list_roles
     if (self.ephorte_role.is_standard_role(person.entity_id,
                                            role,
                                            ou.entity_id,
                                            arkivdel,
                                            journalenhet)
             and len(_list_roles(person_id=person.entity_id)) > 1):
         raise CerebrumError("Cannot delete standard role.")
     self.ephorte_role.remove_role(person.entity_id,
                                   role,
                                   ou.entity_id,
                                   arkivdel,
                                   journalenhet)
     return "OK, removed %s role for %s" % (text_type(role), person_id)
Esempio n. 4
0
 def _parse_search_params(self, *args):
     """Convert string search pattern to a dict."""
     # TODO: Make the param-search handle spaces and stuff?
     params = defaultdict(list)
     for arg in args:
         try:
             key, value = arg.split(':', 1)
         except ValueError:
             # Ignore argument
             continue
         if key == 'type':
             try:
                 cat, typ = value.split(':')
             except ValueError:
                 raise CerebrumError('Search pattern incomplete')
             try:
                 type_code = int(self.clconst.ChangeType(cat, typ))
             except Errors.NotFoundError:
                 raise CerebrumError('EventType does not exist')
             params['type'].append(type_code)
         elif key == 'is_taken':
             params[key] = self._get_boolean(value)
         else:
             params[key] = value
     return params
Esempio n. 5
0
    def ad_list_attributes(self, operator, attr_type=None, spread=None):
        """List all attributes, limited to given input."""
        if not self.ba.is_superuser(operator.get_entity_id()):
            raise PermissionDenied("Only for superusers, for now")
        # TODO: check if operator has access to the entity

        atr = spr = None
        if attr_type:
            atr = self.const.ADAttribute(attr_type)
            try:
                int(atr)
            except Errors.NotFoundError:
                raise CerebrumError('Unknown AD-attribute type: %s' %
                                    attr_type)
        if spread:
            spr = self.const.Spread(spread)
            try:
                int(spr)
            except Errors.NotFoundError:
                raise CerebrumError('Unknown spread: %s' % spread)
        ent = EntityADMixin(self.db)
        return [{
            'attr_type': str(self.const.ADAttribute(row['attr_code'])),
            'spread': str(self.const.Spread(row['spread_code'])),
            'entity': self._get_entity_name(row['entity_id']),
            'value': row['value']
        } for row in ent.list_ad_attributes(spread=spr, attribute=atr)]
Esempio n. 6
0
    def validate_auth_data(self, auth_method, auth_data):
        """Check that sip secrets match our rules.
        """

        if not isinstance(auth_data, (str, unicode)):
            raise CerebrumError("Invalid type of auth data: %s "
                                "(expected str)" % (type(auth_data)))

        if auth_method not in self.valid_auth_methods:
            return self.__super.validate_auth_data(auth_method, auth_data)

        # Sip secrets have to follow a few rules.
        # all chars are from a preset alphabet
        if not all(x in self.sip_secret_alphabet
                   for x in auth_data):
            raise CerebrumError("Invalid chars in auth_data %s" %
                                auth_data)

        # secret is at least 15 characters in length
        if len(auth_data) < self.sip_secret_length:
            raise CerebrumError("auth data %s too short: "
                                "seen %d chars, required %d" %
                                (auth_data, len(auth_data),
                                 self.sip_secret_length))
        return True
Esempio n. 7
0
    def _get_entity(self, entity_type=None, ident=None):
        """ Return a suitable entity subclass for the specified entity_id.

        This method is useful when we have entity_id only, but want the most
        specific object for that id.
        """
        if ident is None:
            raise CerebrumError("Invalid id")
        if entity_type in ('account', self.const.entity_account):
            return self._get_account(ident)
        if entity_type in ('group', self.const.entity_group):
            return self._get_group(ident)
        if entity_type == 'stedkode':
            return self._get_ou(stedkode=ident)
        if entity_type == 'person':
            return self._get_person(*self._map_person_id(ident))
        if entity_type is None:
            id_type, ident = self._human_repr2id(ident)
            if id_type == "id":
                ent = Entity.Entity(self.db)
                ent.find(ident)
            else:
                raise CerebrumError(
                    "Unknown/unsupported id_type %s for id %s" %
                    (id_type, str(ident)))
            # The find*() calls give us an entity_id from ident. The call
            # below returns the most specific object for that numeric
            # entity_id.
            entity_id = int(ent.entity_id)
            ent.clear()
            return ent.get_subclassed_object(entity_id)
        raise CerebrumError("Invalid entity type: %s" % str(entity_type))
    def api_subscription_set(self, operator, identifier, account_id,
                             description=None):
        """Set api client identifier to user mapping"""
        # check araguments
        if not identifier:
            raise CerebrumError("Invalid identifier")
        account = self._get_account(account_id)

        # check permissions
        self.ba.can_modify_api_mapping(operator.get_entity_id(),
                                       account=account)

        keys = ApiMapping(self.db)
        try:
            row = keys.get(identifier)
            if row['account_id'] != account.entity_id:
                raise CerebrumError("Identifier already assigned")
        except Errors.NotFoundError:
            pass

        keys.set(identifier, account.entity_id, description)
        return {
            'identifier': identifier,
            'account_id': account.entity_id,
            'account_name': account.account_name,
            'description': description,
        }
Esempio n. 9
0
    def _get_ou(self, ou_id=None, stedkode=None):
        """ Fetch a specified OU instance.

        Either ou_id or stedkode must be provided.

        @type ou_id: int or None
        @param ou_id:
          ou_id (entity_id) if not None.

        @type stedkode: string (DDDDDD, where D is a digit)
        @param stedkode:
          Stedkode for OU if not None.
        """
        ou = self.OU_class(self.db)
        ou.clear()
        try:
            if ou_id is not None:
                ou.find(ou_id)
            else:
                if len(stedkode) != 6 or not stedkode.isdigit():
                    raise CerebrumError("Expected 6 digits in stedkode <%s>" %
                                        stedkode)
                ou.find_stedkode(stedkode[:2],
                                 stedkode[2:4],
                                 stedkode[4:],
                                 institusjon=cereconf.DEFAULT_INSTITUSJONSNR)
            return ou
        except Errors.NotFoundError:
            raise CerebrumError("Unknown OU (%s)" %
                                (ou_id and ("id=%s" % ou_id) or
                                 ("sko=%s" % stedkode)))
        assert False, "NOTREACHED"
Esempio n. 10
0
    def find_school(self, operator, name):

        if not self.ba.is_schoolit(operator.get_entity_id(), True):
            raise PermissionDenied("Currently limited to superusers and"
                                   " school IT")

        # name could be an acronym or a "regular" name
        result = set()
        for name_variant in (self.const.ou_name, self.const.ou_name_acronym):
            result.update(r["entity_id"]
                          for r in self.ou.search_name_with_language(
                              entity_type=self.const.entity_ou,
                              name_variant=name_variant,
                              name=name,
                              name_language=self.const.language_nb,
                              exact_match=False))

        if len(result) == 0:
            raise CerebrumError("Could not find school matching %s" % name)
        elif len(result) > 1:
            raise CerebrumError("Found several schools with matching names")

        # Now there is just one left. But can the operator see it?
        ou_id = result.pop()
        # filter the results for school IT
        if not self._operator_sees_ou(operator, ou_id):
            raise CerebrumError("School information is unavailable for this"
                                " user")
        else:
            return ou_id
Esempio n. 11
0
 def ephorte_add_perm(self, operator, person_id, tilgang, sko):
     if not self.ba.can_add_ephorte_perm(operator.get_entity_id()):
         raise PermissionDenied("Currently limited to ephorte admins")
     operator_id = operator.get_entity_id()
     try:
         person = self.util.get_target(person_id, restrict_to=['Person'])
     except Errors.TooManyRowsError:
         raise CerebrumError("Unexpectedly found more than one person")
     if not person.has_spread(self.const.spread_ephorte_person):
         raise CerebrumError("Person has no ephorte roles")
     ou = self._get_ou(stedkode=sko)
     if not (sko == cereconf.EPHORTE_EGNE_SAKER_SKO
             or ou.has_spread(self.const.spread_ephorte_ou)):
         raise CerebrumError("Cannot assign permission to a non-ephorte OU")
     # This is a hack needed by the archivists.
     # If one of the new permissions, defined in
     # EPHORTE_NEW2OLD_PERMISSIONS.values() is to be added, the old
     # (expired) one must be added to. And vice versa.
     corresponding_perm = cereconf.EPHORTE_NEW2OLD_PERMISSIONS.get(tilgang, None) or \
                          cereconf.EPHORTE_OLD2NEW_PERMISSIONS.get(tilgang, None)
     if corresponding_perm:
         # Add the corresponding permission
         self.ephorte_perm.add_permission(
             person.entity_id, self._get_tilgang(corresponding_perm),
             ou.entity_id, operator_id)
         ret_msg_suffix = " Also added 'tilgang' %s" % corresponding_perm
     else:
         ret_msg_suffix = ""
     # Add new permission
     self.ephorte_perm.add_permission(person.entity_id,
                                      self._get_tilgang(tilgang),
                                      ou.entity_id, operator_id)
     return "OK, added 'tilgang' %s for %s.%s" % (tilgang, person_id,
                                                  ret_msg_suffix)
    def _get_mappings(self, account, password, tpl):
        """ Get mappings for a given template.

        :param Cerebrum.Account account: The account to generate mappings for
        :param str password: The account's password
        :param dict tpl: The template to generate mappings for

        :return dict: A dictionary of mappings for the TemplateHandler.

        """
        if tpl['type'] == 'letter' and \
           account.owner_type != self.const.entity_person:
            raise CerebrumError(
                "Cannot make letter to non-personal account {}".format(
                    account.account_name))

        mappings = mappers.get_account_mappings(account, password)

        if account.owner_type == self.const.entity_group:
            mappings.update(self._get_group_account_mappings(account))
        elif account.owner_type == self.const.entity_person:
            mappings.update(
                self._get_person_account_mappings(account, tpl['type']))
        else:
            raise CerebrumError("Unsupported account owner type %s".format(
                account.owner_type))
        return mappings
Esempio n. 13
0
 def _get_person(self, idtype, id):
     """ Get person. """
     # TODO: Normalize the arguments. This should have similar usage to
     # _get_account, _get_group, ...
     # Also, document the idtype/id combinations.
     person = self.Person_class(self.db)
     person.clear()
     try:
         if str(idtype) == 'account_name':
             ac = self._get_account(id, idtype='name')
             id = ac.owner_id
             idtype = "entity_id"
         if isinstance(idtype, _CerebrumCode):
             person.find_by_external_id(idtype, id)
         elif idtype in ('entity_id', 'id'):
             if isinstance(id, str) and not id.isdigit():
                 raise CerebrumError("Entity id must be a number")
             person.find(id)
         else:
             raise CerebrumError("Unknown idtype")
     except Errors.NotFoundError:
         raise CerebrumError("Could not find person with %s=%s" %
                             (idtype, id))
     except Errors.TooManyRowsError:
         raise CerebrumError("ID not unique %s=%s" % (idtype, id))
     return person
Esempio n. 14
0
    def user_release_guest(self, operator, *args):
        """ Manually release guest users that was requested earlier. """
        guests = []
        if not args:
            raise CerebrumError(
                "Usage: user release_guest [<guest> || <range>]+")
        # Each arg should be an guest account name or an interval
        for arg in args:
            if '-' in arg:
                first, last = arg.split('-')
                prefix = first.rstrip('0123456789')
                first = int(first[len(prefix):])
                last = int(last)
                for i in range(first, last + 1):
                    guests.append('%s%03d' % (prefix, i))
            else:
                guests.append(arg)

        for guest in guests:
            try:
                owner_id = self.bgu.get_owner(guest)
                owner_group = self.util.get_target(owner_id)
                self.ba.can_release_guests(operator.get_entity_id(),
                                           owner_group.group_name)
                self.bgu.release_guest(guest, operator.get_entity_id())
            except Errors.NotFoundError:
                raise CerebrumError("Could not find guest user with name %s" %
                                    guest)
            except PermissionDenied:
                raise CerebrumError("No permission to release guest user %s" %
                                    guest)
            except GuestAccountException, e:
                raise CerebrumError("Could not release guest user. %s" %
                                    str(e))
Esempio n. 15
0
 def misc_sms_message(self, operator, account_name, message):
     """
     Sends SMS message(s)
     """
     if not self.ba.is_superuser(operator.get_entity_id()):
         raise PermissionDenied('Only superusers may send messages by SMS')
     # Get person object
     person = self._get_person('account_name', account_name)
     # Select phone number, filter out numbers from systems where we do not
     # have an affiliation.
     try:
         spec = map(
             lambda (s, t):
             (self.const.human2constant(s), self.const.human2constant(t)),
             cereconf.SMS_NUMBER_SELECTOR)
         mobile = person.sort_contact_info(spec, person.get_contact_info())
         person_in_systems = [
             int(af['source_system'])
             for af in person.list_affiliations(person_id=person.entity_id)
         ]
         mobile = filter(lambda x: x['source_system'] in person_in_systems,
                         mobile)[0]['contact_value']
     except IndexError:
         raise CerebrumError(
             'No applicable phone number for {}'.format(account_name))
     # Send SMS
     if getattr(cereconf, 'SMS_DISABLE', False):
         self.logger.info('SMS disabled in cereconf, would have '
                          'sent password SMS to {}'.format(mobile))
     else:
         sms = SMSSender(logger=self.logger)
         if not sms(mobile, message, confirm=True):
             raise CerebrumError(
                 'Unable to send message to {}. Aborting.'.format(mobile))
     return {'number': mobile}
Esempio n. 16
0
 def ad_set_attribute(self, operator, entity_type, id, attr_type, spread,
                      value):
     """Set an attribute for a given entity."""
     if not self.ba.is_superuser(operator.get_entity_id()):
         raise PermissionDenied("Only for superusers, for now")
     # TODO: check if operator has access to the entity
     ent = self._get_entity(entity_type, id)
     atr = self.const.ADAttribute(attr_type)
     try:
         int(atr)
     except Errors.NotFoundError:
         raise CerebrumError('Unknown AD-attribute type: %s' % attr_type)
     spr = self.const.Spread(spread)
     try:
         int(spr)
     except Errors.NotFoundError:
         raise CerebrumError('Unknown spread: %s' % spread)
     ent.set_ad_attribute(spread=spr, attribute=atr, value=value)
     ent.write_db()
     # Check if the spread and attribute is defined for an AD-sync. If not,
     # add a warning to the output.
     extra = ''
     config = getattr(cereconf, 'AD_SPREADS', None)
     if config:
         if spread not in config:
             extra = '\nWARNING: No AD-sync defined for spread: %s' % spread
         elif attr_type not in config[spread].get('attributes', ()):
             extra = '\nWARNING: AD-sync for %s does not know of: %s' % (
                 attr_type, spread)
     return "AD-attribute %s set for %s, limited to spread %s: %s%s" % (
         atr, self._get_entity_name(ent.entity_id), spr, value, extra)
    def ephorte_history(self, operator, person_id, limit=100):
        if not self.ba.can_list_ephorte_perm(operator.get_entity_id()):
            raise PermissionDenied("Currently limited to ephorte admins")
        try:
            person = self.util.get_target(person_id, restrict_to=['Person'])
        except Errors.TooManyRowsError:
            raise CerebrumError("Unexpectedly found more than one person")

        try:
            limit = int(limit)
        except ValueError:
            raise CerebrumError("Limit must be a number")

        # Only certain tyeps of changes are relevant for ephorte history
        types = ["ephorte_role_add", "ephorte_role_upd", "ephorte_role_rem",
                 "ephorte_perm_add", "ephorte_perm_rem", "person_aff_add",
                 "person_aff_del", "person_aff_mod", "person_aff_src_add",
                 "person_aff_src_del", "person_aff_src_mod", "person_create"]
        ret = []

        rows = list(self.db.get_log_events(0,
                                           subject_entity=person.entity_id,
                                           types=[getattr(self.clconst, t)
                                                  for t in types]))
        for r in rows[-limit:]:
            ret.append(self._format_changelog_entry(r))
        return ret
Esempio n. 18
0
    def _get_voip_service(self, designation):
        """Locate a specific voip_service.

        We try to be a bit lax when it comes to identifying voip_services. A
        numeric designation is interpreted as entity_id. Everything else is
        interpreted as description.
        """

        service = VoipService(self.db)
        if self._get_entity_id(designation):
            try:
                service.find(self._get_entity_id(designation))
                return service
            except Errors.NotFoundError:
                raise CerebrumError("Could not find voip service with id=%s" %
                                    str(designation))

        ids = service.search_voip_service_by_description(designation,
                                                         exact_match=True)
        if len(ids) == 1:
            service.find(ids[0]["entity_id"])
            return service

        raise CerebrumError("Could not uniquely determine voip_service "
                            "from description %s" % str(designation))
Esempio n. 19
0
    def policy_role_create(self,
                           operator,
                           name,
                           description,
                           foundation,
                           foundation_date=None):
        """Adds a new role and its data. Its can only consist of lowercased,
        alpha numrice characters and -."""
        self.ba.assert_dns_superuser(operator.get_entity_id())
        role = Role(self.db)
        # validate data
        tmp = role.illegal_attr(description)
        if tmp:
            raise CerebrumError('Illegal description: %s' % tmp)
        tmp = role.illegal_attr(foundation)
        if tmp:
            raise CerebrumError('Illegal foundation: %s' % tmp)
        foundation_date = self._parse_date(foundation_date)

        # check that name isn't already in use
        try:
            comp = self._get_component(name)
        except CerebrumError:
            pass
        else:
            raise CerebrumError('A policy already exists with name: %s' % name)
        role.populate(name, description, foundation, foundation_date)
        role.write_db()
        return "New role %s created" % role.component_name
Esempio n. 20
0
    def subnet_set_reserved(self, operator, identifier, new_res):
        self.ba.assert_dns_superuser(operator.get_entity_id())
        s = Subnet(self.db)
        try:
            int(new_res)
        except:
            raise CerebrumError("The number of reserved addresses must be " +
                                "an integer; '%s' isn't" % new_res)

        if new_res < 0:
            raise CerebrumError("Cannot set number of reserved addresses to " +
                                "a negative number such as '%s'" % new_res)

        s.find(identifier)
        old_res = s.no_of_reserved_adr

        s.no_of_reserved_adr = int(new_res)
        s.calculate_reserved_addresses()

        in_use = ""
        if new_res > old_res:
            try:
                s.check_reserved_addresses_in_use()
            except SubnetError, se:
                in_use = "\nFYI: %s" % str(se)
Esempio n. 21
0
    def api_subscription_clear(self, operator, identifier):
        """Remove mapping for a given api client identifier"""
        if not identifier:
            raise CerebrumError("Invalid identifier")

        keys = ApiMapping(self.db)
        try:
            mapping = keys.get(identifier)
        except Errors.NotFoundError:
            raise CerebrumError("Unknown subscription identifier %r" %
                                (identifier,))

        # check permissions
        account = self.Account_class(self.db)
        account.find(mapping['account_id'])
        self.ba.can_modify_api_mapping(operator.get_entity_id(),
                                       account=account)

        if not mapping:
            raise CerebrumError('No identifier=%r for account %s (%d)' %
                                (identifier, account.account_name,
                                 account.entity_id))
        keys.delete(identifier)
        return {
            'identifier': mapping['identifier'],
            'account_id': account.entity_id,
            'account_name': account.account_name,
            'description': mapping['description'],
        }
Esempio n. 22
0
 def __find_ou(self, ou):
     # Try to find the OU the user wants to edit
     ou_class = self.OU_class(self.db)
     if ou.startswith("id:"):
         ou = ou[3:]
         # Assume we got the entity id of the ou
         try:
             ou_class.find(ou)
         except Errors.NotFoundError:
             raise CerebrumError("Unknown OU id {}".format(
                 six.text_type(ou)))
     elif len(ou) == 6:
         # Assume we got a stedkode
         fakultet = ou[:2]
         institutt = ou[2:4]
         avdeling = ou[4:]
         institusjon = cereconf.DEFAULT_INSTITUSJONSNR
         try:
             ou_class.find_stedkode(fakultet, institutt, avdeling,
                                    institusjon)
         except Errors.NotFoundError:
             raise CerebrumError("Unknown OU with stedkode {}".format(
                 six.text_type(ou)))
     else:
         raise CerebrumError(
             "Unable to parse OU id or stedkode {}".format(ou))
     return ou_class
Esempio n. 23
0
    def parse_ipv4(ip):
        """
        Checks if an IP has leading zeroes in its parts, which are not handled
        by the DNS-server. Raises an error if this is the case. Assumes that
        ip-param is a valid ip that has passed the is_valid_ipv4 check.

        Examples: 10.0.10.1 - valid
                  10.0.10.01 - invalid
                  10.0.10 - valid
                  10.0.010 - invalid

        :param ip: An incomplete or complete IPv4.
        :type  ip: str

        """
        parts = ip.split('.')
        # Check for leading zeroes.
        if not IPUtils.is_valid_ipv4(ip):
            raise CerebrumError("Invalid IPv4 address: %s" % ip)
        for part in parts:
            if part.startswith('0') and not len(part) == 1:
                raise CerebrumError("Invalid IPv4-address: %s\n"
                                    "IPv4-address or subnet-fields may not "
                                    "contain leading zeroes.\n"
                                    "Valid example: 10.0.0.1\n"
                                    "Invalid example: 10.0.0.01" % ip)
Esempio n. 24
0
    def ou_homedir_add(self, operator, disk, ou, aff=None):
        """Set default home dir for aff at OU

        :param operator:
        :param str ou:
        :param str or None aff:
        :param str disk:
        :rtype: dict
        :return: client output
        """
        ou_class = self.__find_ou(ou)
        # Check if allowed to set default home dir for this Aff at this OU
        if not self.ba.can_add_ou_path(operator.get_entity_id(),
                                       ou_class.entity_id):
            raise NO_ACCESS_ERROR

        # Try to find the Affiliation the user wants to edit
        aff_str = "*"
        status = None
        if aff:
            try:
                aff, status = self.const.get_affiliation(aff)
            except Errors.NotFoundError:
                raise CerebrumError('Unknown affiliation {}'.format(aff))
            if status:
                aff_str = six.text_type(status)
            else:
                aff_str = six.text_type(aff)

        # Try to find the disk the users want to set
        disk_class = Factory.get("Disk")(self.db)
        if disk.startswith("id:") or disk.isdigit():
            # Assume this is an entity id
            try:
                disk_class.find(disk)
            except Errors.NotFoundError:
                raise CerebrumError("Unknown disk with id {}".format(
                    six.text_type(disk)))
        else:
            # Assume the user wrote a path
            try:
                disk_class.find_by_path(disk)
            except Errors.NotFoundError:
                raise CerebrumError("Unknown disk with path {}".format(
                    six.text_type(disk)))

        # Set the path and return some information to the user
        ous = OUDiskMapping(self.db)
        ous.add(ou_class.entity_id, aff, status, disk_class.entity_id)
        return {
            "ou":
            ou_class.entity_id,
            "aff":
            aff_str,
            "path":
            six.text_type(disk_class.path),
            "stedkode":
            "with stedkode {} ".format(ou_class.get_stedkode()) if hasattr(
                ou_class, 'get_stedkode') else ""
        }
Esempio n. 25
0
    def add_revmap_override(self, ip_host_id, dest_host, force):
        if ip_host_id.count(':') > 2:
            ip_type = dns.IPv6_NUMBER
            a_type = dns.A_RECORD
        else:
            ip_type = dns.IP_NUMBER
            a_type = dns.A_RECORD

        if dest_host:
            dns_owner_ref, same_type = self._validator.dns_reg_owner_ok(
                dest_host, a_type)
            self._dns_owner.clear()
            try:
                self._dns_owner.find_by_name(dest_host)
                dest_host = self._dns_owner.entity_id
            except Errors.NotFoundError:
                if not force:
                    raise CerebrumError("'%s' does not exist, must force (y)" %
                                        dest_host)
                dest_host = self.alloc_dns_owner(dest_host)
        else:
            dest_host = None

        try:
            ip_owner_id = self._find.find_target_by_parsing(
                ip_host_id, ip_type)
        except (Errors.NotFoundError, CerebrumError):
            if not force:
                raise CerebrumError("IP '%s' does not exist, must force (y)" %
                                    ip_host_id)
            ip_owner_id = self.alloc_ip(ip_host_id)

        self._update_helper.add_reverse_override(ip_owner_id, dest_host)
    def subnet_set_reserved(self, operator, identifier, new_res):
        self.ba.assert_dns_superuser(operator.get_entity_id())
        try:
            new_res = int(new_res)
        except:
            raise CerebrumError("The number of reserved addresses must be "
                                "an integer; %r isn't" % new_res)

        if new_res < 0:
            raise CerebrumError("Cannot set number of reserved addresses to " +
                                "a negative number such as '%s'" % new_res)

        s = self._get_subnet(identifier)

        old_res = s.no_of_reserved_adr

        s.no_of_reserved_adr = new_res
        s.calculate_reserved_addresses()

        res = [{
            'subnet_id': _subnet_to_identifier(s),
            'old_reserved': old_res,
            'new_reserved': new_res,
        }]

        if new_res > old_res:
            try:
                s.check_reserved_addresses_in_use()
            except SubnetError as se:
                res.append({
                    'warning': text_type(se),
                })

        s.write_db(perform_checks=False)
        return res
Esempio n. 27
0
    def parse_subnet_or_ip(self, ip_id):
        """Parse ip_id either as a subnet, or as an IP-number.

        Return: (subnet, ip)
          - subnet is None if unknown
          - ip is only set if the user requested a specific IP

        A request for a subnet is identified by a trailing /, or for IPv4 an
        IP with < 4 octets. IPv6-subnets must always be specified with a
        trailing /, followed by a mask number. Examples::

          129.240.200    -> adress on 129.240.200.0/23
          129.240.200.0/ -> adress on 129.240.200.0/23
          129.240.200.0  -> explicit IP
          2001:700:100:2::/64 -> address on 2001:700:100:2::/64
          2001:700:100:2::3   -> explicit IP
        """
        tmp = ip_id.split("/")
        ip = tmp[0]
        subnet_slash = len(tmp) > 1
        full_ip = False

        if IPUtils.is_valid_ipv4(ip):  # ipv4
            IPUtils.parse_ipv4(ip)

            if ip.count('.') == 3 and not subnet_slash:
                full_ip = True

            elif ip.count('.') == 3 and subnet_slash or \
                    ip.count('.') == 2 and not subnet_slash:
                pass

            else:
                raise CerebrumError(("'%s' does not look like a valid subnet "
                                     "or ip-address.") % ip_id)

        elif IPv6Utils.is_valid_ipv6(ip_id):  # full ipv6
            full_ip = True
            ip = ip_id

        elif IPv6Subnet.IPv6Subnet.is_valid_subnet(ip_id):
            ip = ip_id

        else:
            try:  # Assume hostname
                self._arecord.clear()
                self._arecord.find_by_name(self.qualify_hostname(ip))
                self._ip_number.clear()
                self._ip_number.find(self._arecord.ip_number_id)
            except Errors.NotFoundError:
                raise CerebrumError("Could not find host %s" % ip)
            ip = self._ip_number.a_ip

        try:
            ipc = Find(self._db, None)
            subnet_ip = ipc._find_subnet(ip)
        except:
            subnet_ip = None
        return subnet_ip, full_ip and ip or None
Esempio n. 28
0
    def event_info(self, operator, event_id):
        if not self.ba.is_postmaster(operator.get_entity_id()):
            raise PermissionDenied('No access to event')

        try:
            ev = self.db.get_event(event_id)
        except ValueError:
            raise CerebrumError("Error: Event id must be an integer")
        except Errors.NotFoundError:
            raise CerebrumError('Error: No such event exists!')

        # For certain keys, convert constants to human-readable representations
        change_params = ev['change_params']
        if change_params:
            change_params = json.loads(ev['change_params'])
            change_params = self._make_constants_human_readable(change_params)
            change_params = repr(change_params)
        else:
            change_params = None

        ret = {
            'event_id':
            ev['event_id'],
            'event_type':
            six.text_type(self.clconst.map_const(ev['event_type'])),
            'target_system':
            six.text_type(self.const.map_const(ev['target_system'])),
            'failed':
            ev['failed'],
            'tstamp':
            ev['tstamp'],
            'taken_time':
            ev['taken_time'],
            'subject_entity':
            ev['subject_entity'],
            'dest_entity':
            ev['dest_entity'],
            'change_params':
            change_params,
        }

        en = Factory.get('Entity')(self.db)

        # Look up types and names for subject and destination entities
        for key in ('subject_entity', 'dest_entity'):
            if ev[key]:
                try:
                    en.clear()
                    en.find(ev[key])
                    entity_type = six.text_type(
                        self.const.map_const(en.entity_type))
                    entity_name = self._get_entity_name(
                        en.entity_id, en.entity_type)
                    ret[key] = '{} {} (id:{:d})'.format(
                        entity_type, entity_name, en.entity_id)
                except Exception:
                    pass

        return ret
Esempio n. 29
0
 def user_create(self, operator, *args):
     if args[0].startswith('group:'):
         group_id, np_type, spread, email_server, uname = args
         owner_type = self.const.entity_group
         owner_id = self._get_group(group_id.split(":")[1]).entity_id
         np_type = self._get_constant(self.const.Account, np_type,
                                      "account type")
         affiliation = None
         owner_type = self.const.entity_group
     else:
         if len(args) == 6:
             (idtype, person_id, affiliation, spread, email_server,
              uname) = args
         else:
             (idtype, person_id, yes_no, affiliation, spread, email_server,
              uname) = args
         person = self._get_person("entity_id", person_id)
         owner_type, owner_id = self.const.entity_person, person.entity_id
         np_type = None
     account = self.Account_class(self.db)
     account.clear()
     if not self.ba.is_superuser(operator.get_entity_id()):
         raise PermissionDenied("only superusers may reserve users")
     account.populate(
         uname,
         owner_type,  # Owner type
         owner_id,
         np_type,  # np_type
         operator.get_entity_id(),  # creator_id
         None)  # expire_date
     account.write_db()
     for s in cereconf.BOFHD_NEW_USER_SPREADS:
         account.add_spread(self.const.Spread(s))
     if spread:
         try:
             account.add_spread(self.const.Spread(spread))
         except Errors.NotFoundError:
             raise CerebrumError("No such spread: %r" % spread)
     account.write_db()
     try:
         account._update_email_server(email_server)
     except Errors.NotFoundError:
         raise CerebrumError("No such email server: %r" % email_server)
     passwd = account.make_passwd(uname)
     account.set_password(passwd)
     try:
         account.write_db()
         if affiliation is not None:
             ou_id, affiliation = affiliation['ou_id'], affiliation['aff']
             self._user_create_set_account_type(account, person.entity_id,
                                                ou_id, affiliation)
     except self.db.DatabaseError as m:
         raise CerebrumError("Database error: %s" % m)
     operator.store_state("new_account_passwd", {
         'account_id': int(account.entity_id),
         'password': passwd
     })
     return {'account_id': int(account.entity_id)}
Esempio n. 30
0
def check_ac_basics(ac, correct_ac_type):
    """Checks if an account is deleted, expired or not belonging to a person"""
    if ac.is_deleted():
        raise CerebrumError('Account is deleted')
    elif ac.is_expired():
        raise CerebrumError('Account has expired')
    elif ac.owner_type != correct_ac_type:
        raise CerebrumError('Account is not owned by a person')
    return