def test_container_cn_rename_uppercase_rollback(self, udm, ucr): """Rename a container/cn with un-moveable subobjects from lower to upper case""" user_name = uts.random_string() network_name = uts.random_string() cn_name = uts.random_string() cn_name_new = cn_name.upper() cn = udm.create_object('container/cn', name=cn_name) wait_for_drs_replication('cn=%s' % cn_name) udm.create_user(position=cn, username=user_name) udm.create_object('networks/network', position=cn, name=network_name, network='1.1.1.1', netmask='24') with pytest.raises(udm_test.UCSTestUDM_ModifyUDMObjectFailed): udm.modify_object('container/cn', dn=cn, name=cn_name_new) new_cn = 'cn=%s,%s' % (ldap.dn.escape_dn_chars(cn_name_new), ucr.get('ldap/base')) new_user = '******' % (ldap.dn.escape_dn_chars(user_name), ldap.dn.escape_dn_chars(cn_name_new), ucr.get('ldap/base')) utils.verify_ldap_object(new_cn, should_exist=True) utils.verify_ldap_object(new_user, should_exist=True) lo = utils.get_ldap_connection() for dn, entry in lo.search( filter=ldap.filter.filter_format('cn=%s', [cn_name])): assert entry.get('cn')[0] == cn_name.encode( 'UTF-8'), 'cn = %s; expected: %s' % (entry.get('cn')[0], cn_name)
def _wait_for_drs_removal(self, modulename, dn, verbose=True): ad_ldap_search_args = self.ad_object_identifying_filter(modulename, dn) if ad_ldap_search_args: wait_for_drs_replication(should_exist=False, verbose=verbose, timeout=20, **ad_ldap_search_args)
def move_object(self, modulename, wait_for_replication=True, check_for_drs_replication=False, **kwargs): if not modulename: raise UCSTestUDM_MissingModulename() dn = kwargs.get('dn') if not dn: raise UCSTestUDM_MissingDn() if dn not in self._cleanup.get(modulename, set()): raise UCSTestUDM_CannotModifyExistingObject(dn) cmd = self._build_udm_cmdline(modulename, 'move', kwargs) print('Moving %s object %s' % (modulename, _prettify_cmd(cmd))) child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False) (stdout, stderr) = child.communicate() if child.returncode: raise UCSTestUDM_MoveUDMObjectFailed({'module': modulename, 'kwargs': kwargs, 'returncode': child.returncode, 'stdout': stdout, 'stderr': stderr}) for line in stdout.splitlines(): # :pylint: disable-msg=E1103 if line.startswith('Object modified: '): self._cleanup.get(modulename, []).remove(dn) new_dn = ldap.dn.dn2str(ldap.dn.str2dn(dn)[0:1] + ldap.dn.str2dn(kwargs.get('position', ''))) self._cleanup.setdefault(modulename, []).append(new_dn) break else: raise UCSTestUDM_ModifyUDMUnknownDN({'module': modulename, 'kwargs': kwargs, 'stdout': stdout, 'stderr': stderr}) if wait_for_replication: utils.wait_for_replication(verbose=False) if check_for_drs_replication: if utils.package_installed('univention-samba4'): wait_for_drs_replication(ldap.filter.filter_format('cn=%s', (ldap.dn.str2dn(dn)[0][0][1],))) return new_dn
def test_container_cn_modification_set_description(self, udm): """Set description during container/cn modification""" description = uts.random_string() cn_name = uts.random_name() cn = udm.create_object('container/cn', name=cn_name) wait_for_drs_replication('cn=%s' % cn_name) udm.modify_object('container/cn', dn=cn, description=description) utils.verify_ldap_object(cn, {'description': [description]})
def test_container_cn_modification_set_description_with_special_characters( self, udm): """Set description during container/cn modification special characters""" description = uts.random_string() cn_name = uts.random_name_special_characters() cn = udm.create_object('container/cn', name=cn_name) wait_for_drs_replication(ldap.filter.filter_format('cn=%s', [cn_name])) udm.modify_object('container/cn', dn=cn, description=description) utils.verify_ldap_object(cn, {'description': [description]})
def modify_object(self, modulename, wait_for_replication=True, check_for_drs_replication=False, **kwargs): """ Modifies a LDAP object via UDM. Values for UDM properties can be passed via keyword arguments only and have to exactly match UDM property names (case-sensitive!). Please note: the object has to be created by create_object otherwise this call will raise an exception! :param str modulename: name of UDM module (e.g. 'users/user') """ if not modulename: raise UCSTestUDM_MissingModulename() dn = kwargs.get('dn') if not dn: raise UCSTestUDM_MissingDn() if dn not in self._cleanup.get(modulename, set()): raise UCSTestUDM_CannotModifyExistingObject(dn) cmd = self._build_udm_cmdline(modulename, 'modify', kwargs) print('Modifying %s object with %s' % (modulename, _prettify_cmd(cmd))) child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False) (stdout, stderr) = child.communicate() if child.returncode: raise UCSTestUDM_ModifyUDMObjectFailed({'module': modulename, 'kwargs': kwargs, 'returncode': child.returncode, 'stdout': stdout, 'stderr': stderr}) for line in stdout.splitlines(): # :pylint: disable-msg=E1103 if line.startswith('Object modified: '): dn = line.split('Object modified: ', 1)[-1] if dn != kwargs.get('dn'): print('modrdn detected: %r ==> %r' % (kwargs.get('dn'), dn)) if kwargs.get('dn') in self._cleanup.get(modulename, []): self._cleanup.setdefault(modulename, []).append(dn) self._cleanup[modulename].remove(kwargs.get('dn')) break elif line.startswith('No modification: '): raise UCSTestUDM_NoModification({'module': modulename, 'kwargs': kwargs, 'stdout': stdout, 'stderr': stderr}) else: raise UCSTestUDM_ModifyUDMUnknownDN({'module': modulename, 'kwargs': kwargs, 'stdout': stdout, 'stderr': stderr}) if wait_for_replication: utils.wait_for_replication(verbose=False) if check_for_drs_replication: if utils.package_installed('univention-samba4'): wait_for_drs_replication(ldap.filter.filter_format('cn=%s', (ldap.dn.str2dn(dn)[0][0][1],))) return dn
def create_object(self, modulename, wait_for_replication=True, check_for_drs_replication=False, **kwargs): r""" Creates a LDAP object via UDM. Values for UDM properties can be passed via keyword arguments only and have to exactly match UDM property names (case-sensitive!). :param str modulename: name of UDM module (e.g. 'users/user') :param bool wait_for_replication: delay return until Listener has settled. :param bool check_for_drs_replication: delay return until Samab4 has settled. :param \*\*kwargs: """ if not modulename: raise UCSTestUDM_MissingModulename() dn = None cmd = self._build_udm_cmdline(modulename, 'create', kwargs) print('Creating %s object with %s' % (modulename, _prettify_cmd(cmd))) child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False) (stdout, stderr) = child.communicate() if child.returncode: raise UCSTestUDM_CreateUDMObjectFailed({'module': modulename, 'kwargs': kwargs, 'returncode': child.returncode, 'stdout': stdout, 'stderr': stderr}) # find DN of freshly created object and add it to cleanup list for line in stdout.splitlines(): # :pylint: disable-msg=E1103 if line.startswith('Object created: ') or line.startswith('Object exists: '): dn = line.split(': ', 1)[-1] if not line.startswith('Object exists: '): self._cleanup.setdefault(modulename, []).append(dn) break else: raise UCSTestUDM_CreateUDMUnknownDN({'module': modulename, 'kwargs': kwargs, 'stdout': stdout, 'stderr': stderr}) if wait_for_replication: utils.wait_for_replication(verbose=False) if check_for_drs_replication: if utils.package_installed('univention-samba4'): if "options" not in kwargs or "kerberos" in kwargs["options"]: wait_for_drs_replication(ldap.filter.filter_format('cn=%s', (ldap.dn.str2dn(dn)[0][0][1],))) return dn
def wait_for(conditions=None, verbose=True): """Wait for all kind of replications""" for replicationtype, detail in conditions or []: if replicationtype == ReplicationType.LISTENER: if detail == 'postrun': wait_for_listener_replication_and_postrun(verbose) else: wait_for_listener_replication(verbose) elif replicationtype == ReplicationType.S4C_FROM_UCS: wait_for_s4connector_replication(verbose) if detail: # TODO: search in Samba/AD with filter=detail pass elif replicationtype == ReplicationType.S4C_TO_UCS: wait_for_s4connector_replication(verbose) if detail: # TODO: search in OpenLDAP with filter=detail pass elif replicationtype == ReplicationType.DRS: from univention.testing.ucs_samba import wait_for_drs_replication if not isinstance(detail, dict): detail = {'ldap_filter': detail} wait_for_drs_replication(verbose=verbose, **detail)
def wait_for(conditions=None, verbose=True): # type: (Optional[List[Tuple[ReplicationType, Any]]], bool) -> None """Wait for all kind of replications""" for replicationtype, detail in conditions or []: if replicationtype == ReplicationType.LISTENER: if detail == 'postrun': wait_for_listener_replication_and_postrun(verbose) else: wait_for_listener_replication(verbose) elif replicationtype == ReplicationType.S4C_FROM_UCS: wait_for_s4connector_replication(verbose) if detail: # TODO: search in Samba/AD with filter=detail pass elif replicationtype == ReplicationType.S4C_TO_UCS: wait_for_s4connector_replication(verbose) if detail: # TODO: search in OpenLDAP with filter=detail pass elif replicationtype == ReplicationType.DRS: if not isinstance(detail, dict): detail = {'ldap_filter': detail} wait_for_drs_replication(verbose=verbose, **detail)
def test_container_ou_rename_uppercase_rollback_with_special_characters( self, udm, ucr): """Rename a container/ou with un-moveable subobjects from lower to upper case with special characters""" user_name = uts.random_string() network_name = uts.random_string() ou_name = uts.random_name_special_characters() ou_name_new = ou_name.upper() ou = udm.create_object('container/ou', name=ou_name) wait_for_drs_replication(ldap.filter.filter_format('ou=%s', [ou_name])) udm.create_user(position=ou, username=user_name) udm.create_object('networks/network', position=ou, name=network_name, network='1.1.1.1', netmask='24') with pytest.raises(udm_test.UCSTestUDM_ModifyUDMObjectFailed) as exc: udm.modify_object('container/ou', dn=ou, name=ou_name_new) # This operation is not allowed on this object: Unable to move object ayj9blkm9k (networks/network) in subtree, trying to revert changes. assert 'Unable to move object' in str(exc.value) new_ou = 'ou=%s,%s' % (ldap.dn.escape_dn_chars(ou_name_new), ucr.get('ldap/base')) new_user = '******' % (ldap.dn.escape_dn_chars(user_name), ldap.dn.escape_dn_chars(ou_name_new), ucr.get('ldap/base')) utils.verify_ldap_object(new_ou, should_exist=True) utils.verify_ldap_object(new_user, should_exist=True) lo = utils.get_ldap_connection() for dn, entry in lo.search( filter=ldap.filter.filter_format('ou=%s', (ou_name, ))): assert entry.get('ou')[0] == ou_name.encode( 'UTF-8'), 'ou = %s; expected: %s' % (entry.get('ou')[0], ou_name)
def wait_for_drs_replication_of_membership(self, group_dn, member_uid, is_member=True, try_resync=True, **kwargs): """ wait_for_drs_replication() of a user to become a member of a group. :param group: str: DN of a group :param member_uid: str: username :param is_member: bool: whether the user should be a member or not :param try_resync: bool: if waiting for drs replication didn't succeed, run "/usr/share/univention-s4-connector/resync_object_from_ucs.py <group_dn>" and wait again :param kwargs: dict: will be passed to wait_for_drs_replication() with a modified 'ldap_filter' :return: None | <ldb result> """ try: user_filter = kwargs['ldap_filter'] if user_filter and not user_filter.startswith('('): user_filter = '({})'.format(user_filter) except KeyError: user_filter = '' if is_member: member_filter = '(memberOf={})'.format(escape_filter_chars(group_dn)) else: member_filter = '(!(memberOf={}))'.format(escape_filter_chars(group_dn)) kwargs['ldap_filter'] = '(&(cn={}){}{})'.format( escape_filter_chars(member_uid), member_filter, user_filter ) res = wait_for_drs_replication(**kwargs) if not res: self.log.warn('No result from wait_for_drs_replication().') if try_resync: cmd = ['/usr/share/univention-s4-connector/resync_object_from_ucs.py', group_dn] self.log.info('Running subprocess.call(%r)...', cmd) subprocess.call(cmd) self.log.info('Waiting again. Executing: wait_for_drs_replication_of_membership(group_dn=%r, member_uid=%r, is_member=%r, try_resync=False, **kwargs=%r)...', group_dn, member_uid, is_member, kwargs) # recursion once with try_resync=False res = self.wait_for_drs_replication_of_membership(group_dn=group_dn, member_uid=member_uid, is_member=is_member, try_resync=False, **kwargs) return res
def wait_for_drs_replication(*args, **kwargs): from univention.testing.ucs_samba import wait_for_drs_replication return wait_for_drs_replication(*args, **kwargs)