def from_binddn(cls, lo): logger.debug('All local schools: Showing all OUs which DN %s can read.', lo.binddn) # get all schools of the user which are present on this server user_schools = lo.search(base=lo.binddn, scope='base', attr=['ucsschoolSchool'])[0][1].get('ucsschoolSchool', []) if user_schools: schools = [] for ou in user_schools: try: schools.append(cls.from_dn(cls(name=ou).dn, None, lo)) except noObject: pass return cls._filter_local_schools(schools, lo) if 'ou=' in lo.binddn: # user has no ucsschoolSchool attribute (not migrated yet) # we got an OU in the user DN -> school teacher or assistent # restrict the visibility to current school # (note that there can be schools with a DN such as ou=25g18,ou=25,dc=...) school_dn = lo.binddn[lo.binddn.find('ou='):] logger.debug('Schools from binddn: Found an OU in the LDAP binddn. Restricting schools to only show %s', school_dn) school = cls.from_dn(school_dn, None, lo) logger.debug('Schools from binddn: Found school: %r', school) return cls._filter_local_schools([school], lo) logger.warning('Schools from binddn: Unable to identify OU of this account - showing all local OUs!') return School.get_all(lo)
def attach(self, obj, lo): # add univentionPolicyReference if neccessary oc = lo.get(obj.dn, ['objectClass']) if 'univentionPolicyReference' not in oc.get('objectClass', []): try: lo.modify(obj.dn, [('objectClass', '', 'univentionPolicyReference')]) except: logger.warning( 'Objectclass univentionPolicyReference cannot be added to %r', obj) return # add the missing policy pl = lo.get(obj.dn, ['univentionPolicyReference']) logger.info('Attaching %r to %r', self, obj) if self.dn.lower() not in map(lambda x: x.lower(), pl.get('univentionPolicyReference', [])): modlist = [('univentionPolicyReference', '', self.dn)] try: lo.modify(obj.dn, modlist) except: logger.warning('Policy %s cannot be referenced to %r', self, obj) else: logger.info('Already attached!')
def create_mail_domain(self, lo): mail_domain = self.get_mail_domain() if mail_domain is not None and not mail_domain.exists(lo): if self.shall_create_mail_domain(): mail_domain.create(lo) else: logger.warning('Not allowed to create %r.', mail_domain)
def create_without_hooks(self, lo, validate): district = self.get_district() if district: ou = OU(name=district) ou.position = ucr.get('ldap/base') ou.create(lo, False) # setting class_share_file_server and home_share_file_server: # 1. set to None # 2. create school # 3. (maybe) create file_servers <- that is why this is necessary # 4. set file_servers # 5. modify school saved_class_share_file_server = self.class_share_file_server saved_home_share_file_server = self.home_share_file_server self.class_share_file_server = None self.home_share_file_server = None try: success = super(School, self).create_without_hooks(lo, validate) if not success: logger.warning('Creating %r failed (maybe it already exists?)! Trying to set it up nonetheless', self) self.modify_without_hooks(lo) # In a single server environment the default DHCP container must # be set to the DHCP container in the school ou. Otherwise newly # imported computers have the DHCP objects in the wrong DHCP container if ucr.is_true('ucsschool/singlemaster', False): if not ucr.get('dhcpd/ldap/base'): handler_set(['dhcpd/ldap/base=cn=dhcp,%s' % (self.dn)]) ucr.load() self.create_default_containers(lo) self.create_default_groups(lo) self.add_host_to_dc_group(lo) if not self.add_domain_controllers(lo): return False if self.dc_name_administrative: self.create_dc_slave(lo, self.dc_name_administrative, administrative=True) dhcp_service = self.get_dhcp_service(self.dc_name_administrative) dhcp_service.create(lo) dhcp_service.add_server(self.dc_name_administrative, lo) finally: logger.debug('Resetting share file servers from None to %r and %r', saved_home_share_file_server, saved_class_share_file_server) self.class_share_file_server = saved_class_share_file_server self.home_share_file_server = saved_home_share_file_server self.class_share_file_server = self.get_class_share_file_server(lo) self.home_share_file_server = self.get_home_share_file_server(lo) logger.debug('Now it is %r and %r - %r should be modified accordingly', self.home_share_file_server, self.class_share_file_server, self) self.modify_without_hooks(lo) # if requested, then create dhcp_dns policy that clears univentionDhcpDomainNameServers at OU level # to prevent problems with "wrong" DHCP DNS policy connected to ldap base if ucr.is_true('ucsschool/import/generate/policy/dhcp/dns/clearou', False): policy = DHCPDNSPolicy(name='dhcp-dns-clear', school=self.name, empty_attributes=['univentionDhcpDomainNameServers']) policy.create(lo) policy.attach(self, lo) return success
def get_ipv4_network(self): if self.subnet_mask is not None: network_str = '%s/%s' % (self.ip_address, self.subnet_mask) else: network_str = str(self.ip_address) try: return IPv4Network(network_str) except (AddressValueError, NetmaskValueError, ValueError): logger.warning('Unparsable network: %r', network_str)
def get_school_obj(self, lo): from ucsschool.lib.models.school import School if not self.supports_school(): return None school = School.cache(self.school) try: return School.from_dn(school.dn, None, lo) except noObject: logger.warning('%r does not exist!', school) return None
def add_umc_policy(self, policy_dn, lo): if not policy_dn or policy_dn.lower() == 'none': logger.warning('No policy added to %r', self) return try: policy = UMCPolicy.from_dn(policy_dn, self.school, lo) except noObject: logger.warning( 'Object to be referenced does not exist (or is no UMC-Policy): %s', policy_dn) else: policy.attach(self, lo)
def lookup(cls, lo, school, filter_s='', superordinate=None): try: return udm_modules.lookup(cls._meta.udm_module, None, lo, filter=filter_s, base=cls.get_container(school), scope='sub', superordinate=superordinate) except noObject: logger.warning( 'Error while getting all %s of %s: probably %r does not exist!', cls.__name__, school, cls.get_container(school)) return []
def get_share_fileserver_dn(self, set_by_self, lo): if set_by_self: set_by_self = self.get_name_from_dn(set_by_self) or set_by_self hostname = set_by_self or self.get_dc_name() if hostname == self.get_dc_name_fallback(): # does not matter if exists or not - dc object will be created later host = SchoolDC(name=hostname, school=self.name) return host.dn host = AnyComputer.get_first_udm_obj(lo, 'cn=%s' % escape_filter_chars(hostname)) if host: return host.dn else: logger.warning('Could not find %s. Using this host as ShareFileServer ("%s").', hostname, ucr.get('hostname')) return ucr.get('ldap/hostdn')
def get_server_fqdn(self, lo): domainname = ucr.get('domainname') school = self.get_school_obj(lo) school_dn = school.dn # fetch serverfqdn from OU result = lo.get(school_dn, ['ucsschoolClassShareFileServer']) if result: server_domain_name = lo.get( result['ucsschoolClassShareFileServer'][0], ['associatedDomain']) if server_domain_name: server_domain_name = server_domain_name['associatedDomain'][0] else: server_domain_name = domainname result = lo.get(result['ucsschoolClassShareFileServer'][0], ['cn']) if result: return '%s.%s' % (result['cn'][0], server_domain_name) # get alternative server (defined at ou object if a dc slave is responsible for more than one ou) ou_attr_ldap_access_write = lo.get(school_dn, ['univentionLDAPAccessWrite']) alternative_server_dn = None if len(ou_attr_ldap_access_write) > 0: alternative_server_dn = ou_attr_ldap_access_write[ 'univentionLDAPAccessWrite'][0] if len(ou_attr_ldap_access_write) > 1: logger.warning( 'more than one corresponding univentionLDAPAccessWrite found at ou=%s', self.school) # build fqdn of alternative server and set serverfqdn if alternative_server_dn: alternative_server_attr = lo.get(alternative_server_dn, ['uid']) if len(alternative_server_attr) > 0: alternative_server_uid = alternative_server_attr['uid'][0] alternative_server_uid = alternative_server_uid.replace( '$', '') if len(alternative_server_uid) > 0: return '%s.%s' % (alternative_server_uid, domainname) # fallback return '%s.%s' % (school.get_dc_name_fallback(), domainname)
def move_without_hooks(self, lo, udm_obj, force=False): if udm_obj is None: udm_obj = self.get_udm_object(lo) if udm_obj is None: logger.warning('No UDM object found to move from (%r)', self) return False if self.supports_school() and self.get_school_obj(lo) is None: logger.warn('%r wants to move itself to a not existing school', self) return False logger.info('Moving %r to %r', udm_obj.dn, self) if udm_obj.dn == self.dn: logger.warning('%r wants to move to its own DN!', self) return False if force or self._meta.allow_school_change: try: self.do_move(udm_obj, lo) finally: self.invalidate_cache() self.set_dn(self.dn) else: logger.warning( 'Would like to move %s to %r. But it is not allowed!', udm_obj.dn, self) return False return True
def from_udm_obj( cls, udm_obj, school, lo ): # Design fault. school is part of the DN or the ucsschoolSchool attribute. '''Creates a new instance with attributes of the udm_obj. Uses get_class_for_udm_obj() ''' cls.init_udm_module(lo) klass = cls.get_class_for_udm_obj(udm_obj, school) if klass is None: logger.warning( 'UDM object %s does not correspond to a class in UCS school lib!', udm_obj.dn) raise UnknownModel(udm_obj.dn, cls) if klass is not cls: logger.info('UDM object %s is not %s, but actually %s', udm_obj.dn, cls.__name__, klass.__name__) if not issubclass(klass, cls): # security! # ExamStudent must not be converted into Teacher/Student/etc., # SchoolClass must not be converted into ComputerRoom # while Group must be converted into ComputerRoom, etc. and User must be converted into Student, etc. raise WrongModel(udm_obj.dn, klass, cls) return klass.from_udm_obj(udm_obj, school, lo) udm_obj.open() attrs = { 'school': cls.get_school_from_dn(udm_obj.dn) or school } # TODO: is this adjustment okay? for name, attr in cls._attributes.iteritems(): if attr.udm_name: udm_value = udm_obj[attr.udm_name] if udm_value == '': udm_value = None attrs[name] = udm_value obj = cls(**deepcopy(attrs)) obj.set_dn(udm_obj.dn) obj._udm_obj_searched = True obj._udm_obj = udm_obj return obj
def create_dc_slave(self, lo, name, administrative=False): if administrative and not self.shall_create_administrative_objects(): logger.warning('Not creating %s: An administrative DC shall not be created as by UCR variable %r', name, 'ucsschool/ldap/noneducational/create/objects') return False if not self.exists(lo): logger.error('%r does not exist. Cannot create %s', self, name) return False if administrative: groups = self.get_administrative_group_name('administrative', ou_specific='both', as_dn=True) else: groups = self.get_administrative_group_name('educational', ou_specific='both', as_dn=True) logger.debug('DC shall become member of %r', groups) dc = SchoolDCSlave(name=name, school=self.name, groups=groups) if dc.exists(lo): logger.info('%r exists. Setting groups, do not move to %r!', dc, self) # call dc.move() if really necessary to move return dc.modify(lo, move_if_necessary=False) else: existing_host = AnyComputer.get_first_udm_obj(lo, 'cn=%s' % escape_filter_chars(name)) if existing_host: logger.error('Given host name "%s" is already in use and no domaincontroller slave system. Please choose another name.', name) return False return dc.create(lo)
def remove_from_school(self, school, lo): if not self.exists(lo): logger.warning('User does not exists, not going to remove.') return False try: (self.schools or [school]).remove(school) except ValueError: logger.warning('User is not part of school %r. Not removing.', school) return False if not self.schools: logger.warning('User %r not part of any school, removing it.', self) return self.remove(lo) if self.school == school: if not self.change_school(self.schools[0], lo): return False else: self.remove_from_groups_of_school(school, lo) self.school_classes.pop(school, None) return True
def _legacy_is_staff(cls, school, dn): logger.warning('Using deprecated method is_staff()') search_base = cls.get_search_base(school) return dn.endswith(search_base.staff) or dn.endswith( search_base.teachersAndStaff)
def _legacy_is_exam_student(cls, school, dn): logger.warning('Using deprecated method is_exam_student()') return dn.endswith(cls.get_search_base(school).examUsers)
def move_without_hooks(self, lo, udm_obj=None, force=False): try: if udm_obj is None: try: udm_obj = self.get_only_udm_obj( lo, 'cn=%s' % escape_filter_chars(self.name)) except MultipleObjectsError: logger.error( 'Found more than one DC Slave with hostname "%s"', self.name) return False if udm_obj is None: logger.error('Cannot find DC Slave with hostname "%s"', self.name) return False old_dn = udm_obj.dn school = self.get_school_obj(lo) group_dn = school.get_administrative_group_name('educational', ou_specific=True, as_dn=True) if group_dn not in udm_obj['groups']: logger.error('%r has no LDAP access to %r', self, school) return False if old_dn == self.dn: logger.info( 'DC Slave "%s" is already located in "%s" - stopping here', self.name, self.school) self.set_dn(old_dn) if self.exists_outside_school(lo): if not force: logger.error('DC Slave "%s" is located in another OU - %s', self.name, udm_obj.dn) logger.error('Use force=True to override') return False if school is None: logger.error( 'Cannot move DC Slave object - School does not exist: %r', school) return False self.modify_without_hooks(lo) if school.class_share_file_server == old_dn: school.class_share_file_server = self.dn if school.home_share_file_server == old_dn: school.home_share_file_server = self.dn school.modify_without_hooks(lo) removed = False # find dhcp server object by checking all dhcp service objects for dhcp_service in AnyDHCPService.get_all(lo, None): for dhcp_server in dhcp_service.get_servers(lo): if dhcp_server.name == self.name and not dhcp_server.dn.endswith( ',%s' % school.dn): dhcp_server.remove(lo) removed = True if removed: own_dhcp_service = school.get_dhcp_service() dhcp_server = DHCPServer(name=self.name, school=self.school, dhcp_service=own_dhcp_service) dhcp_server.create(lo) logger.info('Move complete') logger.warning('The DC Slave has to be rejoined into the domain!') finally: self.invalidate_cache() return True
def _legacy_is_admininstrator(cls, school, dn): logger.warning('Using deprecated method is_admininstrator()') return dn.endswith(cls.get_search_base(school).admins)