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)
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)
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
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)]
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
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, }
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"
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
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
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
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))
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}
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
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))
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
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)
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'], }
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
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)
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 "" }
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
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
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
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)}
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