Exemplo n.º 1
0
def add_user(topology):
    """Create a user entry"""

    log.info("Create a user entry: %s" % TEST_USER)
    uentry = Entry(TEST_USER)
    uentry.setValues("objectclass", "top", "extensibleobject")
    uentry.setValues("uid", "test")
    topology.instance.add_s(uentry)
Exemplo n.º 2
0
def add_group(topology):
    """Create a group for the user to have some rights to"""

    log.info("Create a group entry: %s" % TEST_GROUP)
    gentry = Entry(TEST_GROUP)
    gentry.setValues("objectclass", "top", "extensibleobject")
    gentry.setValues("cn", "testgroup")
    topology.instance.add_s(gentry)
Exemplo n.º 3
0
def user(topology):
    """Create user entries"""

    for i in range(0, 2):
        uentry = Entry('uid=test%s,%s' % (i, DEFAULT_SUFFIX))
        uentry.setValues('objectclass', 'top', 'extensibleobject')
        uentry.setValues('uid', 'test')
        topology.standalone.add_s(uentry)
Exemplo n.º 4
0
    def syntaxValidate(self, suffix=DEFAULT_SUFFIX, fstr='objectclass=top', args=None):
        '''
        @param suffix - The suffix the task should validate - default is "dc=example,dc=com"
        @param fstr - The search filter to find entries
        @param args - is a dictionary that contains modifier of the task
                wait: True/[False] - If True,  waits for the completion of the task before to return
        @return exit code
        '''

        cn = 'task-' + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = ('cn=%s,cn=syntax validate,cn=tasks,cn=config' % cn)
        entry = Entry(dn)
        entry.setValues('objectclass', 'top', 'extensibleObject')
        entry.setValues('cn', cn)
        entry.setValues('basedn', suffix)
        entry.setValues('filter', fstr)

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add Syntax Validate task")
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: Syntax Validate (%s) exited with %d" % (cn, exitCode))
        else:
            self.log.info("Syntax Validate task (%s) completed successfully" % (cn))
        return exitCode
Exemplo n.º 5
0
    def bak2db(self, bename=None, backup_dir=None, args=None):
        '''
        Restore a backup by creating a bak2db task

        @param bename - 'commonname'/'cn' of the backend (e.g. 'userRoot')
        @param backup_dir - backup directory
        @param args - is a dictionary that contains modifier of the task
                wait: True/[False] - If True,  waits for the completion of the task before to return

        @return exit code

        @raise ValueError: if bename name does not exist
        '''

        # Checking the parameters
        if not backup_dir:
            raise ValueError("You must specify a backup directory")
        if not os.path.exists(backup_dir):
            raise ValueError("Backup file (%s) does not exist" % backup_dir)

        # If a backend name was provided then verify it
        if bename:
            ents = self.conn.mappingtree.list(bename=bename)
            if len(ents) != 1:
                raise ValueError("invalid backend name: %s" % bename)

        # build the task entry
        cn = "restore_" + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = "cn=%s,%s" % (cn, DN_RESTORE_TASK)
        entry = Entry(dn)
        entry.update({
            'objectclass': ['top', 'extensibleObject'],
            'cn': cn,
            'nsArchiveDir': backup_dir,
            'nsDatabaseType': 'ldbm database'
        })
        if bename:
            entry.update({'nsInstance': bename})

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add the backup task (%s)" % dn)
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: restore task %s exited with %d" % (cn, exitCode))
        else:
            self.log.info("Restore task %s completed successfully" % (cn))
        return exitCode
Exemplo n.º 6
0
    def test_update(self):
        expected = 'pluto minnie'
        given = {'cn': expected}
        t = ('o=pippo', {
             'o': ['pippo'],
             'objectclass': ['organization', 'top']
             })

        e = Entry(t)
        e.update(given)
        assert e.cn == expected, "Bad cn: %s, expected: %s" % (e.cn, expected)
Exemplo n.º 7
0
    def fixupTombstones(self, bename=None, args=None):
        '''
            Trigger a tombstone fixup task on the specified backend

            @param bename - 'commonname'/'cn' of the backend (e.g. 'userRoot').
                            Optional.
            @param args - is a dictionary that contains modifier of the task
                wait: True/[False] - If True,  waits for the completion of the
                                     task before to return

            @return exit code

            @raise ValueError: if bename name does not exist
        '''

        if not bename:
            bename = DEFAULT_BENAME

        # Verify the backend name
        if bename:
            ents = self.conn.mappingtree.list(bename=bename)
            if len(ents) != 1:
                raise ValueError("invalid backend name: %s" % bename)

        cn = "fixupTombstone_" + time.strftime("%m%d%Y_%H%M%S",
                                               time.localtime())
        dn = "cn=%s,%s" % (cn, DN_TOMB_FIXUP_TASK)
        entry = Entry(dn)
        entry.setValues('objectclass', 'top', 'extensibleObject')
        entry.setValues('cn', cn)
        entry.setValues('backend', bename)
        if args and args.get(TASK_TOMB_STRIP, False):
            entry.setValues('stripcsn', 'yes')

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add the fixup tombstone task")
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error(
                "Error: tombstone fixup task %s for backend %s exited with %d"
                % (cn, bename, exitCode))
        else:
            self.log.info(
                "tombstone fixup task %s for backend %s completed successfully"
                % (cn, bename))

        self.dn = dn
        self.entry = entry

        return exitCode
Exemplo n.º 8
0
    def enable_ssl(self, secport=636, secargs=None):
        """Configure SSL support into cn=encryption,cn=config.

            secargs is a dict like {
                'nsSSLPersonalitySSL': 'Server-Cert'
            }
        """
        self._log.debug("config.enable_ssl is deprecated! Use RSA, Encryption instead!")
        self._log.debug("configuring SSL with secargs:%r" % secargs)
        secargs = secargs or {}

        dn_enc = 'cn=encryption,cn=config'
        ciphers = ('-rsa_null_md5,+rsa_rc4_128_md5,+rsa_rc4_40_md5,'
                   '+rsa_rc2_40_md5,+rsa_des_sha,+rsa_fips_des_sha,'
                   '+rsa_3des_sha,+rsa_fips_3des_sha,+tls_rsa_export1024'
                   '_with_rc4_56_sha,+tls_rsa_export1024_with_des_cbc_sha')
        mod = [(ldap.MOD_REPLACE, 'nsSSL3', secargs.get('nsSSL3', 'on')),
               (ldap.MOD_REPLACE, 'nsSSLClientAuth',
                secargs.get('nsSSLClientAuth', 'allowed')),
               (ldap.MOD_REPLACE, 'nsSSL3Ciphers', secargs.get('nsSSL3Ciphers',
                ciphers))]
        self._instance.modify_s(dn_enc, mod)

        dn_rsa = 'cn=RSA,cn=encryption,cn=config'
        e_rsa = Entry(dn_rsa)
        e_rsa.update({
            'objectclass': ['top', 'nsEncryptionModule'],
            'nsSSLPersonalitySSL': secargs.get('nsSSLPersonalitySSL',
                                               'Server-Cert'),
            'nsSSLToken': secargs.get('nsSSLToken', 'internal (software)'),
            'nsSSLActivation': secargs.get('nsSSLActivation', 'on')
        })
        try:
            self._instance.add_s(e_rsa)
        except ldap.ALREADY_EXISTS:
            pass

        mod = [
            (ldap.MOD_REPLACE,
             'nsslapd-security',
             secargs.get('nsslapd-security', 'on')),
            (ldap.MOD_REPLACE,
             'nsslapd-ssl-check-hostname',
             secargs.get('nsslapd-ssl-check-hostname', 'off')),
            (ldap.MOD_REPLACE,
             'nsslapd-secureport',
             str(secport))
        ]
        self._log.debug("trying to modify %r with %r" % (DN_CONFIG, mod))
        self._instance.modify_s(DN_CONFIG, mod)

        fields = 'nsslapd-security nsslapd-ssl-check-hostname'.split()
        return self._instance.getEntry(DN_CONFIG, attrlist=fields)
Exemplo n.º 9
0
    def db2bak(self, backup_dir=None, args=None):
        '''
        Perform a backup by creating a db2bak task

        @param backup_dir - backup directory
        @param args - is a dictionary that contains modifier of the task
                wait: True/[False] - If True,  waits for the completion of the
                                     task before to return

        @return exit code

        @raise ValueError: if bename name does not exist
        '''

        # Checking the parameters
        if not backup_dir:
            raise ValueError("You must specify a backup directory.")

        # build the task entry
        cn = "backup_" + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = "cn=%s,%s" % (cn, DN_BACKUP_TASK)
        entry = Entry(dn)
        entry.update({
            'objectclass': ['top', 'extensibleObject'],
            'cn': cn,
            'nsArchiveDir': backup_dir,
            'nsDatabaseType': 'ldbm database'
        })

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add the backup task (%s)" % dn)
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: backup task %s exited with %d" %
                           (cn, exitCode))
        else:
            self.log.info("Backup task %s completed successfully" % (cn))

        self.dn = dn
        self.entry = entry

        return exitCode
Exemplo n.º 10
0
def add_user(topology):
    """
    Create a user entry
    """

    log.info('Create a user entry: %s' % TEST_USER)
    uentry = Entry(TEST_USER)
    uentry.setValues('objectclass', 'top', 'extensibleobject')
    uentry.setValues('uid', 'test')
    topology.instance.add_s(uentry)
    # This doesn't matter that we re-open the realm
    krb = MitKrb5(realm=REALM)
    krb.create_principal("test")
    # We extract the kt so we can kinit from it
    krb.create_keytab("test", "/tmp/test.keytab")
Exemplo n.º 11
0
    def schemaReload(self, schemadir=None, args=None):
        '''
        @param schemadir - The directory to look for schema files(optional)
        @param args - Is a dictionary that contains modifier of the task
                wait: True/[False] - If True,  waits for the completion of the task before to return
        @return exit code
        '''

        cn = 'task-' + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = ('cn=%s,cn=schema reload task,cn=tasks,cn=config' % cn)
        entry = Entry(dn)
        entry.setValues('objectclass', 'top', 'extensibleObject')
        entry.setValues('cn', cn)
        if schemadir:
            entry.setValues('schemadir', schemadir)

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add Schema Reload task")
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: Schema Reload task (%s) exited with %d" % (cn, exitCode))
        else:
            self.log.info("Schema Reload task (%s) completed successfully" % (cn))
        return exitCode
Exemplo n.º 12
0
    def fixupLinkedAttrs(self, linkdn=None, args=None):
        '''
        @param linkdn - The DN of linked attr config entry (if None all possible configurations are checked)
        @param args - Is a dictionary that contains modifier of the task
                wait: True/[False] - If True,  waits for the completion of the task before to return
        @return exit code
        '''

        cn = 'task-' + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = ('cn=%s,cn=fixup linked attributes,cn=tasks,cn=config' % cn)
        entry = Entry(dn)
        entry.setValues('objectclass', 'top', 'extensibleObject')
        entry.setValues('cn', cn)
        if linkdn:
            entry.setValues('linkdn', linkdn)

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add Fixup Linked Attributes task")
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: Fixup Linked Attributes task (%s) exited with %d" % (cn, exitCode))
        else:
            self.log.info("Fixup Linked Attributes task (%s) completed successfully" % (cn))
        return exitCode
Exemplo n.º 13
0
def group(topology):
    """Create a group entry"""

    gentry = Entry('cn=testgroup,%s' % DEFAULT_SUFFIX)
    gentry.setValues('objectclass', 'top', 'extensibleobject')
    gentry.setValues('cn', 'testgroup')
    for i in range(0, 2):
        gentry.setValues('uniqueMember', 'uid=test%s,%s' % (i, DEFAULT_SUFFIX))
    topology.standalone.add_s(gentry)
Exemplo n.º 14
0
    def automemberMap(self, ldif_in=None, ldif_out=None, args=None):
        '''
        @param ldif_in - Entries to pass into the task for processing
        @param ldif_out - The resulting LDIF of changes from ldif_in
        @param args - is a dictionary that contains modifier of the task
                wait: True/[False] - If True,  waits for the completion
                                     of the task before to return
        @return exit code
        @raise ValueError: if ldif_out/ldif_in is not provided
        '''

        if not ldif_out or not ldif_in:
            raise ValueError("Missing ldif_out and/or ldif_in")

        cn = 'task-' + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = ('cn=%s,cn=automember map updates,cn=tasks,cn=config' % cn)

        entry = Entry(dn)
        entry.setValues('objectclass', 'top', 'extensibleObject')
        entry.setValues('cn', cn)
        entry.setValues('ldif_in', ldif_in)
        entry.setValues('ldif_out', ldif_out)

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add Automember Map Updates task")
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error(
                "Error: Automember Map Updates task (%s) exited with %d" %
                (cn, exitCode))
        else:
            self.log.info(
                "Automember Map Updates task (%s) completed successfully" %
                (cn))

        self.dn = dn
        self.entry = entry

        return exitCode
Exemplo n.º 15
0
    def sysconfigReload(self, configfile=None, logchanges=None, args=None):
        '''
        @param configfile - The sysconfig file:
                            /etc/sysconfig/dirsrv-localhost
        @param logchanges - True/False - Tell the server to log the changes
                                         made by the task
        @param args - is a dictionary that contains modifier of the task
                wait: True/[False] - If True,  waits for the completion of the
                                     task before to return
        @return exit code
        @raise ValueError: If sysconfig file not provided
        '''

        if not configfile:
            raise ValueError("Missing required paramter: configfile")

        cn = 'task-' + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = ('cn=%s,cn=cn=sysconfig reload,cn=tasks,cn=config' % cn)
        entry = Entry(dn)
        entry.setValues('objectclass', 'top', 'extensibleObject')
        entry.setValues('cn', cn)
        entry.setValues('sysconfigfile', configfile)
        if logchanges:
            entry.setValues('logchanges', logchanges)
        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add Sysconfig Reload task")
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: Sysconfig Reload task (%s) exited with %d" %
                           (cn, exitCode))
        else:
            self.log.info("Sysconfig Reload task (%s) completed successfully" %
                          (cn))

        self.dn = dn
        self.entry = entry

        return exitCode
Exemplo n.º 16
0
    def create(self, dbname=DEFAULT_CHANGELOG_DB):
        """Add and return the replication changelog entry.

            If dbname starts with "/" then it's considered a full path,
            otherwise it's relative to self.dbdir
        """
        dn = DN_CHANGELOG
        attribute, changelog_name = dn.split(",")[0].split("=", 1)
        dirpath = os.path.join(self.conn.dbdir, dbname)
        entry = Entry(dn)
        entry.update({
            'objectclass': ("top", "extensibleobject"),
            CHANGELOG_PROPNAME_TO_ATTRNAME[CHANGELOG_NAME]: changelog_name,
            CHANGELOG_PROPNAME_TO_ATTRNAME[CHANGELOG_DIR]:  dirpath
        })
        self.log.debug("adding changelog entry: %r" % entry)
        self.changelogdir = dirpath
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.warn("entry %s already exists" % dn)
        return(dn)
Exemplo n.º 17
0
def complex_aci(topology):
    ACI_TARGET = ('(targetfilter ="(ou=groups)")(targetattr ="uniqueMember '
                  '|| member")')
    ACI_ALLOW = ('(version 3.0; acl "Allow test aci";allow (read, search, '
                 'write)')
    ACI_SUBJECT = ('(userdn="ldap:///dc=example,dc=com??sub?(ou=engineering)" '
                   'and userdn="ldap:///dc=example,dc=com??sub?(manager=uid='
                   'wbrown,ou=managers,dc=example,dc=com) || ldap:///dc=examp'
                   'le,dc=com??sub?(manager=uid=tbrown,ou=managers,dc=exampl'
                   'e,dc=com)" );)')
    ACI_BODY = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT

    gentry = Entry('cn=testgroup,%s' % DEFAULT_SUFFIX)
    gentry.setValues('objectclass', 'top', 'extensibleobject')
    gentry.setValues('cn', 'testgroup')
    gentry.setValues('aci', ACI_BODY)

    topology.standalone.add_s(gentry)

    return ensure_str(ACI_BODY)
Exemplo n.º 18
0
    def automemberExport(self, suffix=DEFAULT_SUFFIX, scope='sub',
                         fstr='objectclass=top', ldif_out=None, args=None):
        '''
        @param suffix - The suffix the task should examine - default is
                        "dc=example,dc=com"
        @param scope - The scope of the search to find entries
        @param fstr - The search filter to find entries
        @param ldif_out - The name for the output LDIF file
        @param args - is a dictionary that contains modifier of the task
                wait: True/[False] - If True,  waits for the completion of
                                     the task before to return
        @return exit code
        @raise ValueError: if ldif_out is not provided
        '''

        if not ldif_out:
            raise ValueError("Missing ldif_out")

        cn = 'task-' + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = ('cn=%s,cn=automember export updates,cn=tasks,cn=config' % cn)
        entry = Entry(dn)
        entry.setValues('objectclass', 'top', 'extensibleObject')
        entry.setValues('cn', cn)
        entry.setValues('basedn', suffix)
        entry.setValues('filter', fstr)
        entry.setValues('scope', scope)
        entry.setValues('ldif', ldif_out)

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add Automember Export Updates task")
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error(
                "Error: Automember Export Updates task (%s) exited with %d" %
                (cn, exitCode))
        else:
            self.log.info(
                "Automember Export Updates task (%s) completed successfully" %
                (cn))

        self.dn = dn
        self.entry = entry

        return exitCode
Exemplo n.º 19
0
def test_ticket47676_skip_oc_at(topology):
    '''
        This test ADD an entry on MASTER1 where 47676 is fixed. Then it checks that entry is replicated
        on MASTER2 (even if on MASTER2 47676 is NOT fixed). Then update on MASTER2.
        If the schema has successfully been pushed, updating Master2 should succeed
    '''
    topology.master1.log.info("\n\n######################### ADD ######################\n")

    # bind as 'cn=Directory manager'
    topology.master1.log.info("Bind as %s and add the add the entry with specific oc" % DN_DM)
    topology.master1.simple_bind_s(DN_DM, PASSWORD)

    # Prepare the entry with multivalued members
    entry = Entry(ENTRY_DN)
    entry.setValues('objectclass', 'top', 'person', 'OCticket47676')
    entry.setValues('sn', ENTRY_NAME)
    entry.setValues('cn', ENTRY_NAME)
    entry.setValues('postalAddress', 'here')
    entry.setValues('postalCode', '1234')
    members = []
    for cpt in range(MAX_OTHERS):
        name = "%s%d" % (OTHER_NAME, cpt)
        members.append("cn=%s,%s" % (name, SUFFIX))
    members.append(BIND_DN)
    entry.setValues('member', members)

    topology.master1.log.info("Try to add Add  %s should be successful" % ENTRY_DN)
    topology.master1.add_s(entry)

    #
    # Now check the entry as been replicated
    #
    topology.master2.simple_bind_s(DN_DM, PASSWORD)
    topology.master1.log.info("Try to retrieve %s from Master2" % ENTRY_DN)
    loop = 0
    while loop <= 10:
        try:
            ent = topology.master2.getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)")
            break
        except ldap.NO_SUCH_OBJECT:
            time.sleep(2)
            loop += 1
    assert loop <= 10

    # Now update the entry on Master2 (as DM because 47676 is possibly not fixed on M2)
    topology.master1.log.info("Update  %s on M2" % ENTRY_DN)
    mod = [(ldap.MOD_REPLACE, 'description', 'test_add')]
    topology.master2.modify_s(ENTRY_DN, mod)

    topology.master1.simple_bind_s(DN_DM, PASSWORD)
    loop = 0
    while loop <= 10:
        ent = topology.master1.getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)")
        if ent.hasAttr('description') and (ent.getValue('description') == 'test_add'):
            break
        time.sleep(1)
        loop += 1

    assert ent.getValue('description') == 'test_add'
Exemplo n.º 20
0
    def create(self, suffix=None, properties=None):
        """
            Creates backend entry and returns its dn.

            If the properties 'chain-bind-pwd' and 'chain-bind-dn' and
            'chain-urls' are specified the backend is a chained backend.  A
            chaining backend is created under
                'cn=chaining database,cn=plugins,cn=config'.

            A local backend is created under
                'cn=ldbm database,cn=plugins,cn=config'

            @param suffix - suffix stored in the backend
            @param properties - dictionary with properties values
            supported properties are
                BACKEND_NAME          = 'name'
                BACKEND_READONLY      = 'read-only'
                BACKEND_REQ_INDEX     = 'require-index'
                BACKEND_CACHE_ENTRIES = 'entry-cache-number'
                BACKEND_CACHE_SIZE    = 'entry-cache-size'
                BACKEND_DNCACHE_SIZE  = 'dn-cache-size'
                BACKEND_DIRECTORY     = 'directory'
                BACKEND_DB_DEADLOCK   = 'db-deadlock'
                BACKEND_CHAIN_BIND_DN = 'chain-bind-dn'
                BACKEND_CHAIN_BIND_PW = 'chain-bind-pw'
                BACKEND_CHAIN_URLS    = 'chain-urls'
                BACKEND_SUFFIX        = 'suffix'
                BACKEND_SAMPLE_ENTRIES = 'sample_entries'

            @return backend DN of the created backend

            @raise LDAPError

        """
        def _getBackendName(parent):
            '''
                Use to build a backend name that is not already used
            '''
            index = 1
            while True:
                bename = "local%ddb" % index
                base = ("%s=%s,%s" %
                        (BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_NAME], bename,
                         parent))
                filt = "(objectclass=%s)" % BACKEND_OBJECTCLASS_VALUE
                self.log.debug("_getBackendName: baser=%s : fileter=%s", base,
                               filt)
                try:
                    self.conn.getEntry(base, ldap.SCOPE_BASE, filt)
                except (NoSuchEntryError, ldap.NO_SUCH_OBJECT):
                    self.log.info("backend name will be %s", bename)
                    return bename
                index += 1

        # suffix is mandatory. If may be in the properties
        if isinstance(properties, dict) and properties.get(
                BACKEND_SUFFIX, None) is not None:
            suffix = properties.get(BACKEND_SUFFIX)
        if not suffix:
            raise ldap.UNWILLING_TO_PERFORM('Missing Suffix')
        else:
            nsuffix = normalizeDN(suffix)

        # Check it does not already exist a backend for that suffix
        if self.conn.verbose:
            self.log.info("Checking suffix %s for existence", suffix)
        ents = self.conn.backend.list(suffix=suffix)
        if len(ents) != 0:
            raise ldap.ALREADY_EXISTS
        # Check if we are creating a local/chained backend
        chained_suffix = (properties and (BACKEND_CHAIN_BIND_DN in properties)
                          and (BACKEND_CHAIN_BIND_PW in properties)
                          and (BACKEND_CHAIN_URLS in properties))
        if chained_suffix:
            self.log.info("Creating a chaining backend")
            dnbase = DN_CHAIN
        else:
            self.log.info("Creating a local backend")
            dnbase = DN_LDBM

        # Get the future backend name
        if properties and BACKEND_NAME in properties:
            cn = properties[BACKEND_NAME]
        else:
            cn = _getBackendName(dnbase)

        # Check the future backend name does not already exists
        # we can imagine having no backends for 'suffix' but having a backend
        # with the same name
        dn = "%s=%s,%s" % (BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_NAME], cn,
                           dnbase)
        ents = self.conn.backend.list(backend_dn=dn)
        if ents:
            raise ldap.ALREADY_EXISTS(
                "Backend already exists with that DN: %s" % ents[0].dn)

        # All checks are done, Time to create the backend
        try:
            entry = Entry(dn)
            entry.update({
                'objectclass':
                ['top', 'extensibleObject', BACKEND_OBJECTCLASS_VALUE],
                BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_NAME]:
                cn,
                BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_SUFFIX]:
                nsuffix,
            })

            if chained_suffix:
                entry.update({
                    BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_CHAIN_URLS]:
                    properties[BACKEND_CHAIN_URLS],
                    BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_CHAIN_BIND_DN]:
                    properties[BACKEND_CHAIN_BIND_DN],
                    BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_CHAIN_BIND_PW]:
                    properties[BACKEND_CHAIN_BIND_PW]
                })

            self.log.debug("adding entry: %r", entry)
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS as e:
            self.log.error("Entry already exists: %r", dn)
            raise ldap.ALREADY_EXISTS("%s : %r" % (e, dn))
        except ldap.LDAPError as e:
            self.log.error("Could not add backend entry: %r", dn)
            raise e

        backend_entry = self.conn._test_entry(dn, ldap.SCOPE_BASE)

        return backend_entry
Exemplo n.º 21
0
def test_ticket49122(topo):
    """Search for non-existant role and make sure the server does not crash
    """

    # Enable roles plugin
    topo.standalone.plugins.enable(name=PLUGIN_ROLES)
    topo.standalone.restart()

    # Add test user
    try:
        topo.standalone.add_s(
            Entry((USER_DN, {
                'objectclass': "top extensibleObject".split(),
                'uid': 'user'
            })))
    except ldap.LDAPError as e:
        topo.standalone.log.fatal('Failed to add test user: error ' + str(e))
        assert False

    if DEBUGGING:
        print("Attach gdb")
        time.sleep(20)

    # Loop over filters
    for role_filter in filters:
        log.info('Testing filter: ' + role_filter)

        # Add invalid role
        try:
            topo.standalone.add_s(
                Entry((ROLE_DN, {
                    'objectclass': [
                        'top', 'ldapsubentry', 'nsroledefinition',
                        'nscomplexroledefinition', 'nsfilteredroledefinition'
                    ],
                    'cn':
                    'Filtered_Role_That_Includes_Empty_Role',
                    'nsRoleFilter':
                    role_filter,
                    'description':
                    'A filtered role with filter that will crash the server'
                })))
        except ldap.LDAPError as e:
            topo.standalone.log.fatal('Failed to add filtered role: error ' +
                                      e.message['desc'])
            assert False

        # Search for the role
        try:
            topo.standalone.search_s(USER_DN, ldap.SCOPE_SUBTREE,
                                     'objectclass=*', ['nsrole'])
        except ldap.LDAPError as e:
            topo.standalone.log.fatal('Search failed: error ' + str(e))
            assert False

        # Cleanup
        try:
            topo.standalone.delete_s(ROLE_DN)
        except ldap.LDAPError as e:
            topo.standalone.log.fatal('delete failed: error ' + str(e))
            assert False
        time.sleep(1)

    topo.standalone.log.info('Test Passed')
Exemplo n.º 22
0
    def _test_ticket47560_setup():
        """
        - Create entry cn=group,SUFFIX
        - Create entry cn=member,SUFFIX
        - Update 'cn=member,SUFFIX' to add "memberOf: cn=group,SUFFIX"
        - Enable Memberof Plugins
        """
        log.debug("-------- > _test_ticket47560_setup\n")

        #
        # By default the memberof plugin is disabled create
        # - create a group entry
        # - create a member entry
        # - set the member entry as memberof the group entry
        #
        entry = Entry(group_DN)
        entry.setValues('objectclass', 'top', 'groupOfNames', 'inetUser')
        entry.setValues('cn', 'group')
        try:
            topology_st.standalone.add_s(entry)
        except ldap.ALREADY_EXISTS:
            log.debug("Entry %s already exists" % (group_DN))

        entry = Entry(member_DN)
        entry.setValues('objectclass', 'top', 'person', 'organizationalPerson',
                        'inetorgperson', 'inetUser')
        entry.setValues('uid', 'member')
        entry.setValues('cn', 'member')
        entry.setValues('sn', 'member')
        try:
            topology_st.standalone.add_s(entry)
        except ldap.ALREADY_EXISTS:
            log.debug("Entry %s already exists" % (member_DN))

        replace = [(ldap.MOD_REPLACE, 'memberof', ensure_bytes(group_DN))]
        topology_st.standalone.modify_s(member_DN, replace)

        #
        # enable the memberof plugin and restart the instance
        #
        _enable_disable_mbo('on')

        #
        # check memberof attribute is still present
        #
        filt = 'uid=member'
        ents = topology_st.standalone.search_s(member_DN, ldap.SCOPE_BASE,
                                               filt)
        assert len(ents) == 1
        ent = ents[0]
        # print ent
        value = ensure_str(ent.getValue('memberof'))
        # print "memberof: %s" % (value)
        assert value == group_DN
Exemplo n.º 23
0
def test_ticket47313_run(topology):
    """
        It adds 2 test entries
        Search with filters including subtype and !
            It deletes the added entries
    """

    # bind as directory manager
    topology.standalone.log.info("Bind as %s" % DN_DM)
    topology.standalone.simple_bind_s(DN_DM, PASSWORD)

    # enable filter error logging
    #mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '32')]
    #topology.standalone.modify_s(DN_CONFIG, mod)

    topology.standalone.log.info("\n\n######################### ADD ######################\n")

    # Prepare the entry with cn;fr & cn;en
    entry_name_fr = '%s fr' % (ENTRY_NAME)
    entry_name_en = '%s en' % (ENTRY_NAME)
    entry_name_both = '%s both' % (ENTRY_NAME)
    entry_dn_both = 'cn=%s, %s' % (entry_name_both, SUFFIX)
    entry_both = Entry(entry_dn_both)
    entry_both.setValues('objectclass', 'top', 'person')
    entry_both.setValues('sn', entry_name_both)
    entry_both.setValues('cn', entry_name_both)
    entry_both.setValues('cn;fr', entry_name_fr)
    entry_both.setValues('cn;en', entry_name_en)

    # Prepare the entry with one member
    entry_name_en_only = '%s en only' % (ENTRY_NAME)
    entry_dn_en_only = 'cn=%s, %s' % (entry_name_en_only, SUFFIX)
    entry_en_only = Entry(entry_dn_en_only)
    entry_en_only.setValues('objectclass', 'top', 'person')
    entry_en_only.setValues('sn', entry_name_en_only)
    entry_en_only.setValues('cn', entry_name_en_only)
    entry_en_only.setValues('cn;en', entry_name_en)

    topology.standalone.log.info("Try to add Add %s: %r" % (entry_dn_both, entry_both))
    topology.standalone.add_s(entry_both)

    topology.standalone.log.info("Try to add Add %s: %r" % (entry_dn_en_only, entry_en_only))
    topology.standalone.add_s(entry_en_only)

    topology.standalone.log.info("\n\n######################### SEARCH ######################\n")

    # filter: (&(cn=test_entry en only)(!(cn=test_entry fr)))
    myfilter = '(&(sn=%s)(!(cn=%s)))' % (entry_name_en_only, entry_name_fr)
    topology.standalone.log.info("Try to search with filter %s" % myfilter)
    ents = topology.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
    assert len(ents) == 1
    assert ents[0].sn == entry_name_en_only
    topology.standalone.log.info("Found %s" % ents[0].dn)

    # filter: (&(cn=test_entry en only)(!(cn;fr=test_entry fr)))
    myfilter = '(&(sn=%s)(!(cn;fr=%s)))' % (entry_name_en_only, entry_name_fr)
    topology.standalone.log.info("Try to search with filter %s" % myfilter)
    ents = topology.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
    assert len(ents) == 1
    assert ents[0].sn == entry_name_en_only
    topology.standalone.log.info("Found %s" % ents[0].dn)

    # filter: (&(cn=test_entry en only)(!(cn;en=test_entry en)))
    myfilter = '(&(sn=%s)(!(cn;en=%s)))' % (entry_name_en_only, entry_name_en)
    topology.standalone.log.info("Try to search with filter %s" % myfilter)
    ents = topology.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
    assert len(ents) == 0
    topology.standalone.log.info("Found none")

    topology.standalone.log.info("\n\n######################### DELETE ######################\n")

    topology.standalone.log.info("Try to delete  %s " % entry_dn_both)
    topology.standalone.delete_s(entry_dn_both)

    topology.standalone.log.info("Try to delete  %s " % entry_dn_en_only)
    topology.standalone.delete_s(entry_dn_en_only)

    log.info('Testcase PASSED')
Exemplo n.º 24
0
def makeDSUserEnt(idnum):
    id = str(idnum)
    userid = 'testuser' + id
    dn = 'uid=%s,%s,%s' % (userid, usersubtree, suffix)
    ent = Entry(dn)
    ent.setValues('objectclass', userObjClasses)
    ent.setValues('cn', 'Test User' + id)
    ent.setValues('sn', 'User' + id)
    ent.setValues('uid', userid)
    ent.setValues('userPassword', 'Password' + id)
    ent.setValues('ntUserDomainId', userid)
    ent.setValues('userPassword', 'Ornette1')
    if ipawinsync:
        ent.setValues('krbPrincipalName', '%s@%s' % (userid, realm))
        ent.setValues('uidNumber', str(500 + idnum))
        ent.setValues('gidNumber', '1002')
        ent.setValues('homeDirectory', '/home/' + userid)
        if idnum % 2:
            ent.setValues('description', 'User added disabled to DS')
            ent.setValues('nsAccountLock', 'TRUE')
        else:
            ent.setValues('description', 'User added enabled to DS')
    else:
        ent.setValues('description', 'User added to DS')
        ent.setValues('ntUserCreateNewAccount', 'TRUE')
        ent.setValues('ntUserDeleteAccount', 'TRUE')
    return ent
Exemplo n.º 25
0
def test_ticket49184(topo):
    """Write your testcase here...

    Also, if you need any testcase initialization,
    please, write additional fixture for that(include finalizer).
    """
    
    topo.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
    topo.standalone.restart(timeout=10)

    #
    #  create some users and a group
    #
    log.info('create users and group...')
    for idx in range(1, 5):
        try:
            USER_DN = ("uid=member%d,%s" % (idx, DEFAULT_SUFFIX))
            topo.standalone.add_s(Entry((USER_DN,
                                          {'objectclass': 'top extensibleObject'.split(),
                                           'uid': 'member%d' % (idx)})))
        except ldap.LDAPError as e:
            log.fatal('Failed to add user (%s): error %s' % (USER_DN, e.args[0]['desc']))
            assert False

    # add all users in GROUP_DN_1 and checks each users is memberof GROUP_DN_1
    _add_group_with_members(topo, GROUP_DN_1)
    for idx in range(1, 5):
        USER_DN = ("uid=member%d,%s" % (idx, DEFAULT_SUFFIX))
        _check_memberof(topo, member=USER_DN, memberof=True, group_dn=GROUP_DN_1 )
        
    # add all users in GROUP_DN_2 and checks each users is memberof GROUP_DN_2
    _add_group_with_members(topo, GROUP_DN_2)
    for idx in range(1, 5):
        USER_DN = ("uid=member%d,%s" % (idx, DEFAULT_SUFFIX))
        _check_memberof(topo, member=USER_DN, memberof=True, group_dn=GROUP_DN_2 )
    
    # add the level 2, 3 and 4 group
    for super_grp in (SUPER_GRP1, SUPER_GRP2, SUPER_GRP3):
        topo.standalone.add_s(Entry((super_grp,
                                          {'objectclass': 'top groupofnames extensibleObject'.split(),
                                           'cn': 'super_grp'})))
    topo.standalone.modify_s(SUPER_GRP1,
                                      [(ldap.MOD_ADD,
                                        'member',
                                        ensure_bytes(GROUP_DN_1)),
                                        (ldap.MOD_ADD,
                                        'member',
                                        ensure_bytes(GROUP_DN_2))])
    topo.standalone.modify_s(SUPER_GRP2,
                                      [(ldap.MOD_ADD,
                                        'member',
                                        ensure_bytes(GROUP_DN_1)),
                                        (ldap.MOD_ADD,
                                        'member',
                                        ensure_bytes(GROUP_DN_2))])
    return
    topo.standalone.delete_s(GROUP_DN_2)
    for idx in range(1, 5):
        USER_DN = ("uid=member%d,%s" % (idx, DEFAULT_SUFFIX))
        _check_memberof(topo, member=USER_DN, memberof=True, group_dn=GROUP_DN_1 )
        _check_memberof(topo, member=USER_DN, memberof=False, group_dn=GROUP_DN_2 )
    
    if DEBUGGING:
        # Add debugging steps(if any)...
        pass
Exemplo n.º 26
0
def test_ticket49039(topo):
    """Test "password must change" verses "password min age".  Min age should not
    block password update if the password was reset.
    """

    # Setup SSL (for ldappasswd test)
    topo.standalone.enable_tls()

    # Configure password policy
    try:
        policy = PwPolicyManager(topo.standalone)
        policy.set_global_policy(
            properties={
                'nsslapd-pwpolicy-local': 'on',
                'passwordMustChange': 'on',
                'passwordExp': 'on',
                'passwordMaxAge': '86400000',
                'passwordMinAge': '8640000',
                'passwordChange': 'on'
            })
    except ldap.LDAPError as e:
        log.fatal('Failed to set password policy: ' + str(e))

    # Add user, bind, and set password
    try:
        topo.standalone.add_s(
            Entry((USER_DN, {
                'objectclass': 'top extensibleObject'.split(),
                'uid': 'user1',
                'userpassword': PASSWORD
            })))
    except ldap.LDAPError as e:
        log.fatal('Failed to add user: error ' + e.args[0]['desc'])
        assert False

    # Reset password as RootDN
    try:
        topo.standalone.modify_s(
            USER_DN,
            [(ldap.MOD_REPLACE, 'userpassword', ensure_bytes(PASSWORD))])
    except ldap.LDAPError as e:
        log.fatal('Failed to bind: error ' + e.args[0]['desc'])
        assert False

    time.sleep(1)

    # Reset password as user
    try:
        topo.standalone.simple_bind_s(USER_DN, PASSWORD)
    except ldap.LDAPError as e:
        log.fatal('Failed to bind: error ' + e.args[0]['desc'])
        assert False

    try:
        topo.standalone.modify_s(
            USER_DN,
            [(ldap.MOD_REPLACE, 'userpassword', ensure_bytes(PASSWORD))])
    except ldap.LDAPError as e:
        log.fatal('Failed to change password: error ' + e.args[0]['desc'])
        assert False

    ###################################
    # Make sure ldappasswd also works
    ###################################

    # Reset password as RootDN
    try:
        topo.standalone.simple_bind_s(DN_DM, PASSWORD)
    except ldap.LDAPError as e:
        log.fatal('Failed to bind as rootdn: error ' + e.args[0]['desc'])
        assert False

    try:
        topo.standalone.modify_s(
            USER_DN,
            [(ldap.MOD_REPLACE, 'userpassword', ensure_bytes(PASSWORD))])
    except ldap.LDAPError as e:
        log.fatal('Failed to bind: error ' + e.args[0]['desc'])
        assert False

    time.sleep(1)

    # Run ldappasswd as the User.
    os.environ["LDAPTLS_CACERTDIR"] = topo.standalone.get_cert_dir()
    cmd = ('ldappasswd' + ' -h ' + topo.standalone.host + ' -Z -p 38901 -D ' +
           USER_DN + ' -w password -a password -s password2 ' + USER_DN)
    os.system(cmd)
    time.sleep(1)

    try:
        topo.standalone.simple_bind_s(USER_DN, "password2")
    except ldap.LDAPError as e:
        log.fatal('Failed to bind: error ' + e.args[0]['desc'])
        assert False

    log.info('Test Passed')
Exemplo n.º 27
0
    'description':
    'normal, regular AD account disabled, do not expire password',
    'userAccountControl': 512 + 2 + 65536
}]

userids_disabled = {}
if useds:
    print "Create sub-ou's on the AD side and add users . . ."
    ii = 0
    dns = [
        'ou=people,' + suffix, 'ou=1,ou=people,' + suffix,
        'ou=2,ou=people,' + suffix, 'ou=11,ou=1,ou=people,' + suffix,
        'ou=12,ou=1,ou=people,' + suffix
    ]
    for dn in dns:
        ent = Entry(dn)
        ent.setValues('objectclass', 'organizationalUnit')
        try:
            ad.add_s(ent)
        except ldap.ALREADY_EXISTS:
            pass
        print "Add users to", dn
        for jj in range(0, 5):
            strii = str(ii)
            userdn = 'cn=Test User' + strii + ',' + dn
            ent = Entry(userdn)
            userid = 'userid' + strii
            ent.setValues('objectclass', ['person', 'adPerson'])
            ent.setValues('sn', 'User' + strii)
            ent.setValues('samAccountName', userid)
            ent.setValues('objectGUID', struct.pack('B', ii))
Exemplo n.º 28
0
    def test_update_complex(self):
        # compare two entries created with different methods
        nsuffix, replid, replicatype = ("dc=example,dc=com", 5,
                                        lib389.REPLICA_RDWR_TYPE)
        binddnlist, legacy = ['uid=pippo, cn=config'], 'off'
        dn = "dc=example,dc=com"
        entry = Entry(dn)
        entry.setValues('objectclass', "top", "nsds5replica",
                        "extensibleobject")
        entry.setValues('cn', "replica")
        entry.setValues('nsds5replicaroot', nsuffix)
        entry.setValues('nsds5replicaid', str(replid))
        entry.setValues('nsds5replicatype', str(replicatype))
        entry.setValues('nsds5flags', "1")
        entry.setValues('nsds5replicabinddn', binddnlist)
        entry.setValues('nsds5replicalegacyconsumer', legacy)

        uentry = Entry((dn, {
            'objectclass': ["top", "nsds5replica", "extensibleobject"],
            'cn': ["replica"]
        }))
        log.debug("Entry created with dict:", uentry)
        # Entry.update *replaces*, so be careful with multi-valued attrs
        uentry.update({
            'nsds5replicaroot': nsuffix,
            'nsds5replicaid': str(replid),
            'nsds5replicatype': str(replicatype),
            'nsds5flags': '1',
            'nsds5replicabinddn': binddnlist,
            'nsds5replicalegacyconsumer': legacy
        })
        uentry_s, entry_s = list(map(str, (uentry, entry)))
        assert uentry_s == entry_s, "Mismatching entries [%r] vs [%r]" % (
            uentry, entry)
Exemplo n.º 29
0
 def test_init_badstr(self):
     # This should not be allowed
     with pytest.raises(ValueError):
         e = Entry('no equal sign here')
Exemplo n.º 30
0
 def test_init_with_str(self):
     e = Entry('o=pippo')
     assert e.dn == 'o=pippo'
Exemplo n.º 31
0
    def exportLDIF(self, suffix=None, benamebase=None, output_file=None, args=None):
        '''
        Export in a LDIF format a given 'suffix' (or 'benamebase' that stores that suffix).
        It uses an internal task to acheive this request.

        If 'suffix' and 'benamebase' are specified, it uses 'benamebase' first else 'suffix'.
        If both 'suffix' and 'benamebase' are missing it raises ValueError

        'output_file' is the output file of the export

        @param suffix - suffix of the backend
        @param benamebase - 'commonname'/'cn' of the backend (e.g. 'userRoot')
        @param output_file - file that will contain the exported suffix in LDIF format
        @param args - is a dictionary that contains modifier of the export task
                wait: True/[False] - If True, 'export' waits for the completion of the task before to return
                repl-info: True/[False] - If True, it adds the replication meta data (state information,
                                          tombstones and RUV) in the exported file

        @return None

        @raise ValueError

        '''

        # Checking the parameters
        if not benamebase and not suffix:
            raise ValueError("Specify either bename or suffix")

        if not output_file:
            raise ValueError("output_file is mandatory")

        # Prepare the task entry
        cn = "export_" + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = "cn=%s,%s" % (cn, DN_EXPORT_TASK)
        entry = Entry(dn)
        entry.update({
            'objectclass': ['top', 'extensibleObject'],
            'cn': cn,
            'nsFilename': output_file
        })
        if benamebase:
            entry.setValues('nsInstance', benamebase)
        else:
            entry.setValues('nsIncludeSuffix', suffix)

        if args.get(EXPORT_REPL_INFO, False):
            entry.setValues('nsExportReplica', 'true')

        # start the task and possibly wait for task completion
        self.conn.add_s(entry)
        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: export task %s for file %s exited with %d" % (
                    cn, output_file, exitCode))
        else:
            self.log.info("Export task %s for file %s completed successfully" % (
                    cn, output_file))
        return exitCode
Exemplo n.º 32
0
def makeADUserEnt(idnum):
    id = str(idnum)
    userid = 'testuser' + id
    cn = 'Test User' + id
    dn = 'cn=%s,%s,%s' % (cn, adusersubtree, suffix)
    ent = Entry(dn)
    ent.setValues('objectclass', aduserObjClasses)
    ent.setValues('cn', cn)
    ent.setValues('sn', 'User' + id)
    ent.setValues('userPrincipalName', '%s@%s' % (userid, realm))
    ent.setValues('sAMAccountName', userid)
    return ent
Exemplo n.º 33
0
 def test_init_empty(self):
     e = Entry('')
     assert not e.dn
Exemplo n.º 34
0
def test_ticket47815(topology_st):
    """
        Test betxn plugins reject an invalid option, and make sure that the rejected entry
        is not in the entry cache.

        Enable memberOf, automember, and retrocl plugins
        Add the automember config entry
        Add the automember group
        Add a user that will be rejected by a betxn plugin - result error 53
        Attempt the same add again, and it should result in another error 53 (not error 68)
    """
    result = 0
    result2 = 0

    log.info(
        'Testing Ticket 47815 - Add entries that should be rejected by the betxn plugins, and are not left in the entry cache')

    # Enabled the plugins
    topology_st.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
    topology_st.standalone.plugins.enable(name=PLUGIN_AUTOMEMBER)
    topology_st.standalone.plugins.enable(name=PLUGIN_RETRO_CHANGELOG)

    # configure automember config entry
    log.info('Adding automember config')
    try:
        topology_st.standalone.add_s(Entry(('cn=group cfg,cn=Auto Membership Plugin,cn=plugins,cn=config', {
            'objectclass': 'top autoMemberDefinition'.split(),
            'autoMemberScope': 'dc=example,dc=com',
            'autoMemberFilter': 'cn=user',
            'autoMemberDefaultGroup': 'cn=group,dc=example,dc=com',
            'autoMemberGroupingAttr': 'member:dn',
            'cn': 'group cfg'})))
    except:
        log.error('Failed to add automember config')
        exit(1)

    topology_st.standalone.restart()

    # need to reopen a connection toward the instance
    topology_st.standalone.open()

    # add automember group
    log.info('Adding automember group')
    try:
        topology_st.standalone.add_s(Entry(('cn=group,dc=example,dc=com', {
            'objectclass': 'top groupOfNames'.split(),
            'cn': 'group'})))
    except:
        log.error('Failed to add automember group')
        exit(1)

    # add user that should result in an error 53
    log.info('Adding invalid entry')

    try:
        topology_st.standalone.add_s(Entry(('cn=user,dc=example,dc=com', {
            'objectclass': 'top person'.split(),
            'sn': 'user',
            'cn': 'user'})))
    except ldap.UNWILLING_TO_PERFORM:
        log.debug('Adding invalid entry failed as expected')
        result = 53
    except ldap.LDAPError as e:
        log.error('Unexpected result ' + e.message['desc'])
        assert False
    if result == 0:
        log.error('Add operation unexpectedly succeeded')
        assert False

    # Attempt to add user again, should result in error 53 again
    try:
        topology_st.standalone.add_s(Entry(('cn=user,dc=example,dc=com', {
            'objectclass': 'top person'.split(),
            'sn': 'user',
            'cn': 'user'})))
    except ldap.UNWILLING_TO_PERFORM:
        log.debug('2nd add of invalid entry failed as expected')
        result2 = 53
    except ldap.LDAPError as e:
        log.error('Unexpected result ' + e.message['desc'])
        assert False
    if result2 == 0:
        log.error('2nd Add operation unexpectedly succeeded')
        assert False
Exemplo n.º 35
0
    def create(self, suffix=None, bename=None, parent=None):
        '''
            Create a mapping tree entry (under "cn=mapping tree,cn=config"),
            for the 'suffix' and that is stored in 'bename' backend.
            'bename' backend must exist before creating the mapping tree entry.

            If a 'parent' is provided that means that we are creating a
            sub-suffix mapping tree.

            @param suffix - suffix mapped by this mapping tree entry. It will
                            be the common name ('cn') of the entry
            @param benamebase - backend common name (e.g. 'userRoot')
            @param parent - if provided is a parent suffix of 'suffix'

            @return DN of the mapping tree entry

            @raise ldap.NO_SUCH_OBJECT - if the backend entry or parent mapping
                                         tree does not exist
                   ValueError - if missing a parameter,

        '''
        # Check suffix is provided
        if not suffix:
            raise ValueError("suffix is mandatory")
        else:
            nsuffix = normalizeDN(suffix)

        # Check backend name is provided
        if not bename:
            raise ValueError("backend name is mandatory")

        # Check that if the parent suffix is provided then
        # it exists a mapping tree for it
        if parent:
            nparent = normalizeDN(parent)
            filt = suffixfilt(parent)
            try:
                entry = self.conn.getEntry(DN_MAPPING_TREE, ldap.SCOPE_SUBTREE,
                                           filt)
                pass
            except NoSuchEntryError:
                raise ValueError("parent suffix has no mapping tree")
        else:
            nparent = ""

        # Check if suffix exists, return
        filt = suffixfilt(suffix)
        try:
            entry = self.conn.getEntry(DN_MAPPING_TREE, ldap.SCOPE_SUBTREE,
                                       filt)
            return entry
        except ldap.NO_SUCH_OBJECT:
            entry = None

        #
        # Now start the real work
        #

        # fix me when we can actually used escaped DNs
        dn = ','.join(('cn="%s"' % nsuffix, DN_MAPPING_TREE))
        entry = Entry(dn)
        entry.update({
            'objectclass': ['top', 'extensibleObject', MT_OBJECTCLASS_VALUE],
            'nsslapd-state':
            'backend',
            # the value in the dn has to be DN escaped
            # internal code will add the quoted value - unquoted value is
            # useful for searching.
            MT_PROPNAME_TO_ATTRNAME[MT_SUFFIX]:
            nsuffix,
            MT_PROPNAME_TO_ATTRNAME[MT_BACKEND]:
            bename
        })

        # possibly add the parent
        if parent:
            entry.setValues(MT_PROPNAME_TO_ATTRNAME[MT_PARENT_SUFFIX], nparent)

        try:
            self.log.debug("Creating entry: %s", entry.dn)
            self.log.info("Entry %r", entry)
            self.conn.add_s(entry)
        except ldap.LDAPError as e:
            raise ldap.LDAPError("Error adding suffix entry " + dn, e)

        ret = self.conn._test_entry(dn, ldap.SCOPE_BASE)
        return ret
Exemplo n.º 36
0
def test_memberof_with_changelog_reset(topo_m2):
    """Test that replication does not break, after DS stop-start, due to changelog reset

    :id: 60c11636-55a1-4704-9e09-2c6bcc828de4
    :setup: 2 Masters
    :steps:
        1. On M1 and M2, Enable memberof
        2. On M1, add 999 entries allowing memberof
        3. On M1, add a group with these 999 entries as members
        4. Stop M1 in between,
           when add the group memerof is called and before it is finished the
           add, so step 4 should be executed after memberof has started and
           before the add has finished
        5. Check that replication is working fine
    :expectedresults:
        1. memberof should be enabled
        2. Entries should be added
        3. Add operation should start
        4. M1 should be stopped
        5. Replication should be working fine
    """
    m1 = topo_m2.ms["master1"]
    m2 = topo_m2.ms["master2"]

    log.info("Configure memberof on M1 and M2")
    memberof = MemberOfPlugin(m1)
    memberof.enable()
    memberof.set_autoaddoc('nsMemberOf')
    m1.restart()

    memberof = MemberOfPlugin(m2)
    memberof.enable()
    memberof.set_autoaddoc('nsMemberOf')
    m2.restart()

    log.info("On M1, add 999 test entries allowing memberof")
    users_list = add_users(topo_m2, 999, DEFAULT_SUFFIX)

    log.info("On M1, add a group with these 999 entries as members")
    dic_of_attributes = {
        'cn': ensure_bytes('testgroup'),
        'objectclass': ensure_list_bytes(['top', 'groupOfNames'])
    }

    for user in users_list:
        dic_of_attributes.setdefault('member', [])
        dic_of_attributes['member'].append(user.dn)

    log.info('Adding the test group using async function')
    groupdn = 'cn=testgroup,%s' % DEFAULT_SUFFIX
    m1.add(Entry((groupdn, dic_of_attributes)))

    #shutdown the server in-between adding the group
    m1.stop()

    #start the server
    m1.start()

    log.info("Check the log messages for error")
    error_msg = "ERR - NSMMReplicationPlugin - ruv_compare_ruv"
    assert not m1.ds_error_log.match(error_msg)

    log.info("Check that the replication is working fine both ways, M1 <-> M2")
    repl = ReplicationManager(DEFAULT_SUFFIX)
    repl.test_replication_topology(topo_m2)
Exemplo n.º 37
0
def test_ticket47653_add(topology_st):
    '''
        It checks that, bound as bind_entry,
            - we can not ADD an entry without the proper SELFDN aci.
            - with the proper ACI we can not ADD with 'member' attribute
            - with the proper ACI and 'member' it succeeds to ADD
    '''
    topology_st.standalone.log.info(
        "\n\n######################### ADD ######################\n")

    # bind as bind_entry
    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)

    # Prepare the entry with multivalued members
    entry_with_members = Entry(ENTRY_DN)
    entry_with_members.setValues('objectclass', 'top', 'person',
                                 'OCticket47653')
    entry_with_members.setValues('sn', ENTRY_NAME)
    entry_with_members.setValues('cn', ENTRY_NAME)
    entry_with_members.setValues('postalAddress', 'here')
    entry_with_members.setValues('postalCode', '1234')
    members = []
    for cpt in range(MAX_OTHERS):
        name = "%s%d" % (OTHER_NAME, cpt)
        members.append("cn=%s,%s" % (name, SUFFIX))
    members.append(BIND_DN)
    entry_with_members.setValues('member', members)

    # Prepare the entry with one member
    entry_with_member = Entry(ENTRY_DN)
    entry_with_member.setValues('objectclass', 'top', 'person',
                                'OCticket47653')
    entry_with_member.setValues('sn', ENTRY_NAME)
    entry_with_member.setValues('cn', ENTRY_NAME)
    entry_with_member.setValues('postalAddress', 'here')
    entry_with_member.setValues('postalCode', '1234')
    member = []
    member.append(BIND_DN)
    entry_with_member.setValues('member', member)

    # entry to add WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
    try:
        topology_st.standalone.log.info(
            "Try to add Add  %s (aci is missing): %r" %
            (ENTRY_DN, entry_with_member))

        topology_st.standalone.add_s(entry_with_member)
    except Exception as e:
        topology_st.standalone.log.info("Exception (expected): %s" %
                                        type(e).__name__)
        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)

    # Ok Now add the proper ACI
    topology_st.standalone.log.info("Bind as %s and add the ADD SELFDN aci" %
                                    DN_DM)
    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)

    ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
    ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
    ACI_ALLOW = "(version 3.0; acl \"SelfDN add\"; allow (add)"
    ACI_SUBJECT = " userattr = \"member#selfDN\";)"
    ACI_BODY = ACI_TARGET + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
    mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
    topology_st.standalone.modify_s(SUFFIX, mod)

    # bind as bind_entry
    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)

    # entry to add WITHOUT member and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
    try:
        topology_st.standalone.log.info(
            "Try to add Add  %s (member is missing)" % ENTRY_DN)
        topology_st.standalone.add_s(
            Entry((ENTRY_DN, {
                'objectclass': ENTRY_OC.split(),
                'sn': ENTRY_NAME,
                'cn': ENTRY_NAME,
                'postalAddress': 'here',
                'postalCode': '1234'
            })))
    except Exception as e:
        topology_st.standalone.log.info("Exception (expected): %s" %
                                        type(e).__name__)
        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)

    # entry to add WITH memberS and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
    # member should contain only one value
    try:
        topology_st.standalone.log.info(
            "Try to add Add  %s (with several member values)" % ENTRY_DN)
        topology_st.standalone.add_s(entry_with_members)
    except Exception as e:
        topology_st.standalone.log.info("Exception (expected): %s" %
                                        type(e).__name__)
        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)

    topology_st.standalone.log.info("Try to add Add  %s should be successful" %
                                    ENTRY_DN)
    topology_st.standalone.add_s(entry_with_member)
Exemplo n.º 38
0
def test_unhashed_pw_switch(topo_supplier):
    """Check that nsslapd-unhashed-pw-switch works corrently

    :id: e5aba180-d174-424d-92b0-14fe7bb0b92a
    :setup: Supplier Instance
    :steps:
        1. A Supplier is created, enable retrocl (not  used here)
        2. Create a set of users
        3. update userpassword of user1 and check that unhashed#user#password is not logged (default)
        4. udpate userpassword of user2 and check that unhashed#user#password is not logged ('nolog')
        5. udpate userpassword of user3 and check that unhashed#user#password is logged ('on')
    :expectedresults:
        1. Success
        2. Success
        3.  Success (unhashed#user#password is not logged in the replication changelog)
        4. Success (unhashed#user#password is not logged in the replication changelog)
        5. Success (unhashed#user#password is logged in the replication changelog)
    """
    MAX_USERS = 10
    PEOPLE_DN = ("ou=people," + DEFAULT_SUFFIX)

    inst = topo_supplier.ms["supplier1"]
    inst.modify_s(
        "cn=Retro Changelog Plugin,cn=plugins,cn=config",
        [(ldap.MOD_REPLACE, 'nsslapd-changelogmaxage', b'2m'),
         (ldap.MOD_REPLACE, 'nsslapd-changelog-trim-interval', b"5s"),
         (ldap.MOD_REPLACE, 'nsslapd-logAccess', b'on')])
    inst.config.loglevel(vals=[256 + 4], service='access')
    inst.restart()
    # If you need any test suite initialization,
    # please, write additional fixture for that (including finalizer).
    # Topology for suites are predefined in lib389/topologies.py.

    # enable dynamic plugins, memberof and retro cl plugin
    #
    log.info('Enable plugins...')
    try:
        inst.modify_s(DN_CONFIG,
                      [(ldap.MOD_REPLACE, 'nsslapd-dynamic-plugins', b'on')])
    except ldap.LDAPError as e:
        ldap.error('Failed to enable dynamic plugins! ' + e.message['desc'])
        assert False

    #topology_st.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
    inst.plugins.enable(name=PLUGIN_RETRO_CHANGELOG)
    #topology_st.standalone.modify_s("cn=changelog,cn=ldbm database,cn=plugins,cn=config", [(ldap.MOD_REPLACE, 'nsslapd-cachememsize', str(100000))])
    inst.restart()

    log.info('create users and group...')
    for idx in range(1, MAX_USERS):
        try:
            USER_DN = ("uid=member%d,%s" % (idx, PEOPLE_DN))
            inst.add_s(
                Entry((USER_DN, {
                    'objectclass': 'top extensibleObject'.split(),
                    'uid': 'member%d' % (idx)
                })))
        except ldap.LDAPError as e:
            log.fatal('Failed to add user (%s): error %s' %
                      (USER_DN, e.message['desc']))
            assert False

    # Check default is that unhashed#user#password is not logged on 1.4.1.6+
    user = "******" % (PEOPLE_DN)
    inst.modify_s(user,
                  [(ldap.MOD_REPLACE, 'userpassword', PASSWORD.encode())])
    inst.stop()
    if ds_is_newer('1.4.1.6'):
        _check_unhashed_userpw(inst, user, is_present=False)
    else:
        _check_unhashed_userpw(inst, user, is_present=True)

    #  Check with nolog that unhashed#user#password is not logged
    inst.modify_s(DN_CONFIG,
                  [(ldap.MOD_REPLACE, 'nsslapd-unhashed-pw-switch', b'nolog')])
    inst.restart()
    user = "******" % (PEOPLE_DN)
    inst.modify_s(user,
                  [(ldap.MOD_REPLACE, 'userpassword', PASSWORD.encode())])
    inst.stop()
    _check_unhashed_userpw(inst, user, is_present=False)

    #  Check with value 'on' that unhashed#user#password is logged
    inst.modify_s(DN_CONFIG,
                  [(ldap.MOD_REPLACE, 'nsslapd-unhashed-pw-switch', b'on')])
    inst.restart()
    user = "******" % (PEOPLE_DN)
    inst.modify_s(user,
                  [(ldap.MOD_REPLACE, 'userpassword', PASSWORD.encode())])
    inst.stop()
    _check_unhashed_userpw(inst, user, is_present=True)

    if DEBUGGING:
        # Add debugging steps(if any)...
        pass
Exemplo n.º 39
0
def test_ticket47653_add(topology):
    '''
        This test ADD an entry on MASTER1 where 47653 is fixed. Then it checks that entry is replicated
        on MASTER2 (even if on MASTER2 47653 is NOT fixed). Then update on MASTER2 and check the update on MASTER1

        It checks that, bound as bind_entry,
            - we can not ADD an entry without the proper SELFDN aci.
            - with the proper ACI we can not ADD with 'member' attribute
            - with the proper ACI and 'member' it succeeds to ADD
    '''
    topology.master1.log.info("\n\n######################### ADD ######################\n")

    # bind as bind_entry
    topology.master1.log.info("Bind as %s" % BIND_DN)
    topology.master1.simple_bind_s(BIND_DN, BIND_PW)

    # Prepare the entry with multivalued members
    entry_with_members = Entry(ENTRY_DN)
    entry_with_members.setValues('objectclass', 'top', 'person', 'OCticket47653')
    entry_with_members.setValues('sn', ENTRY_NAME)
    entry_with_members.setValues('cn', ENTRY_NAME)
    entry_with_members.setValues('postalAddress', 'here')
    entry_with_members.setValues('postalCode', '1234')
    members = []
    for cpt in range(MAX_OTHERS):
        name = "%s%d" % (OTHER_NAME, cpt)
        members.append("cn=%s,%s" % (name, SUFFIX))
    members.append(BIND_DN)
    entry_with_members.setValues('member', members)

    # Prepare the entry with only one member value
    entry_with_member = Entry(ENTRY_DN)
    entry_with_member.setValues('objectclass', 'top', 'person', 'OCticket47653')
    entry_with_member.setValues('sn', ENTRY_NAME)
    entry_with_member.setValues('cn', ENTRY_NAME)
    entry_with_member.setValues('postalAddress', 'here')
    entry_with_member.setValues('postalCode', '1234')
    member = []
    member.append(BIND_DN)
    entry_with_member.setValues('member', member)

    # entry to add WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
    try:
        topology.master1.log.info("Try to add Add  %s (aci is missing): %r" % (ENTRY_DN, entry_with_member))

        topology.master1.add_s(entry_with_member)
    except Exception as e:
        topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)

    # Ok Now add the proper ACI
    topology.master1.log.info("Bind as %s and add the ADD SELFDN aci" % DN_DM)
    topology.master1.simple_bind_s(DN_DM, PASSWORD)

    ACI_TARGET       = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
    ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
    ACI_ALLOW        = "(version 3.0; acl \"SelfDN add\"; allow (add)"
    ACI_SUBJECT      = " userattr = \"member#selfDN\";)"
    ACI_BODY         = ACI_TARGET + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
    mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
    topology.master1.modify_s(SUFFIX, mod)
    time.sleep(1)

    # bind as bind_entry
    topology.master1.log.info("Bind as %s" % BIND_DN)
    topology.master1.simple_bind_s(BIND_DN, BIND_PW)

    # entry to add WITHOUT member and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
    try:
        topology.master1.log.info("Try to add Add  %s (member is missing)" % ENTRY_DN)
        topology.master1.add_s(Entry((ENTRY_DN, {
                                            'objectclass':      ENTRY_OC.split(),
                                            'sn':               ENTRY_NAME,
                                            'cn':               ENTRY_NAME,
                                            'postalAddress':    'here',
                                            'postalCode':       '1234'})))
    except Exception as e:
        topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)

    # entry to add WITH memberS and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
    # member should contain only one value
    try:
        topology.master1.log.info("Try to add Add  %s (with several member values)" % ENTRY_DN)
        topology.master1.add_s(entry_with_members)
    except Exception as e:
        topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)

    topology.master1.log.info("Try to add Add  %s should be successful" % ENTRY_DN)
    try:
        topology.master1.add_s(entry_with_member)
    except ldap.LDAPError as e:
        topology.master1.log.info("Failed to add entry,  error: " + e.message['desc'])
        assert False

    #
    # Now check the entry as been replicated
    #
    topology.master2.simple_bind_s(DN_DM, PASSWORD)
    topology.master1.log.info("Try to retrieve %s from Master2" % ENTRY_DN)
    loop = 0
    while loop <= 10:
        try:
            ent = topology.master2.getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)")
            break
        except ldap.NO_SUCH_OBJECT:
            time.sleep(1)
            loop += 1
    assert loop <= 10

    # Now update the entry on Master2 (as DM because 47653 is possibly not fixed on M2)
    topology.master1.log.info("Update  %s on M2" % ENTRY_DN)
    mod = [(ldap.MOD_REPLACE, 'description', 'test_add')]
    topology.master2.modify_s(ENTRY_DN, mod)

    topology.master1.simple_bind_s(DN_DM, PASSWORD)
    loop = 0
    while loop <= 10:
        try:
            ent = topology.master1.getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)")
            if ent.hasAttr('description') and (ent.getValue('description') == 'test_add'):
                break
        except ldap.NO_SUCH_OBJECT:
            time.sleep(1)
            loop += 1

    assert ent.getValue('description') == 'test_add'
Exemplo n.º 40
0
    def abortCleanAllRUV(self, suffix=None, replicaid=None, certify=None, args=None):
        '''
        @param replicaid - The replica ID to remove/clean
        @param certify - True/False - Certify the task was aborted on all the replicas
        @param args - is a dictionary that contains modifier of the task
                wait: True/[False] - If True,  waits for the completion of the task before to return
        @return tuple (task dn, and the exit code)
        @raise ValueError: If missing replicaid
        '''

        if not replicaid:
            raise ValueError("Missing required paramter: replicaid")
        if not suffix:
            raise ValueError("Missing required paramter: suffix")

        cn = 'task-' + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = ('cn=%s,cn=abort cleanallruv,cn=tasks,cn=config' % cn)
        entry = Entry(dn)
        entry.setValues('objectclass', 'top', 'extensibleObject')
        entry.setValues('cn', cn)
        entry.setValues('replica-base-dn', suffix)
        entry.setValues('replica-id', replicaid)
        if certify:
            entry.setValues('replica-certify-all', 'yes')
        else:
            entry.setValues('replica-certify-all', 'no')

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add Abort cleanAllRUV task")
            return (dn, -1)

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: Abort cleanAllRUV task (%s) exited with %d" % (cn, exitCode))
        else:
            self.log.info("Abort cleanAllRUV task (%s) completed successfully" % (cn))
        return (dn, exitCode)
Exemplo n.º 41
0
def test_ticket47462(topology_m2):
    """
        Test that AES properly replaces DES during an update/restart, and that
        replication also works correctly.
    """

    #
    # First set config as if it's an older version.  Set DES to use
    # libdes-plugin, MMR to depend on DES, delete the existing AES plugin,
    # and set a DES password for the replication agreement.
    #
    # Add an extra attribute to the DES plugin args
    #
    try:
        topology_m2.ms["master1"].modify_s(
            DES_PLUGIN, [(ldap.MOD_REPLACE, 'nsslapd-pluginEnabled', 'on')])
    except ldap.LDAPError as e:
        log.fatal('Failed to enable DES plugin, error: ' + e.message['desc'])
        assert False

    try:
        topology_m2.ms["master1"].modify_s(
            DES_PLUGIN, [(ldap.MOD_ADD, 'nsslapd-pluginarg2', 'description')])
    except ldap.LDAPError as e:
        log.fatal('Failed to reset DES plugin, error: ' + e.message['desc'])
        assert False

    try:
        topology_m2.ms["master1"].modify_s(
            MMR_PLUGIN,
            [(ldap.MOD_DELETE, 'nsslapd-plugin-depends-on-named', 'AES')])

    except ldap.NO_SUCH_ATTRIBUTE:
        pass
    except ldap.LDAPError as e:
        log.fatal('Failed to reset MMR plugin, error: ' + e.message['desc'])
        assert False

    #
    # Delete the AES plugin
    #
    try:
        topology_m2.ms["master1"].delete_s(AES_PLUGIN)
    except ldap.NO_SUCH_OBJECT:
        pass
    except ldap.LDAPError as e:
        log.fatal('Failed to delete AES plugin, error: ' + e.message['desc'])
        assert False

    # restart the server so we must use DES plugin
    topology_m2.ms["master1"].restart(timeout=10)

    #
    # Get the agmt dn, and set the password
    #
    try:
        entry = topology_m2.ms["master1"].search_s(
            'cn=config', ldap.SCOPE_SUBTREE,
            'objectclass=nsDS5ReplicationAgreement')
        if entry:
            agmt_dn = entry[0].dn
            log.info('Found agmt dn (%s)' % agmt_dn)
        else:
            log.fatal('No replication agreements!')
            assert False
    except ldap.LDAPError as e:
        log.fatal('Failed to search for replica credentials: ' +
                  e.message['desc'])
        assert False

    try:
        properties = {RA_BINDPW: "password"}
        topology_m2.ms["master1"].agreement.setProperties(
            None, agmt_dn, None, properties)
        log.info('Successfully modified replication agreement')
    except ValueError:
        log.error('Failed to update replica agreement: ' + AGMT_DN)
        assert False

    #
    # Check replication works with the new DES password
    #
    try:
        topology_m2.ms["master1"].add_s(
            Entry((USER1_DN, {
                'objectclass': "top person".split(),
                'sn': 'sn',
                'description': 'DES value to convert',
                'cn': 'test_user'
            })))
        loop = 0
        ent = None
        while loop <= 10:
            try:
                ent = topology_m2.ms["master2"].getEntry(
                    USER1_DN, ldap.SCOPE_BASE, "(objectclass=*)")
                break
            except ldap.NO_SUCH_OBJECT:
                time.sleep(1)
                loop += 1
        if not ent:
            log.fatal('Replication test failed fo user1!')
            assert False
        else:
            log.info('Replication test passed')
    except ldap.LDAPError as e:
        log.fatal('Failed to add test user: '******'desc'])
        assert False

    #
    # Add a backend (that has no entries)
    #
    try:
        topology_m2.ms["master1"].backend.create("o=empty",
                                                 {BACKEND_NAME: "empty"})
    except ldap.LDAPError as e:
        log.fatal('Failed to create extra/empty backend: ' + e.message['desc'])
        assert False

    #
    # Run the upgrade...
    #
    topology_m2.ms["master1"].upgrade('online')
    topology_m2.ms["master1"].restart()
    topology_m2.ms["master2"].restart()

    #
    # Check that the restart converted existing DES credentials
    #
    try:
        entry = topology_m2.ms["master1"].search_s(
            'cn=config', ldap.SCOPE_SUBTREE, 'nsDS5ReplicaCredentials=*')
        if entry:
            val = entry[0].getValue('nsDS5ReplicaCredentials')
            if val.startswith('{AES-'):
                log.info('The DES credentials have been converted to AES')
            else:
                log.fatal('Failed to convert credentials from DES to AES!')
                assert False
        else:
            log.fatal('Failed to find entries with nsDS5ReplicaCredentials')
            assert False
    except ldap.LDAPError as e:
        log.fatal('Failed to search for replica credentials: ' +
                  e.message['desc'])
        assert False

    #
    # Check that the AES plugin exists, and has all the attributes listed in
    # DES plugin.  The attributes might not be in the expected order so check
    # all the attributes.
    #
    try:
        entry = topology_m2.ms["master1"].search_s(AES_PLUGIN, ldap.SCOPE_BASE,
                                                   'objectclass=*')
        if not entry[0].hasValue('nsslapd-pluginarg0', 'description') and \
                not entry[0].hasValue('nsslapd-pluginarg1', 'description') and \
                not entry[0].hasValue('nsslapd-pluginarg2', 'description'):
            log.fatal('The AES plugin did not have the DES attribute copied ' +
                      'over correctly')
            assert False
        else:
            log.info('The AES plugin was correctly setup')
    except ldap.LDAPError as e:
        log.fatal('Failed to find AES plugin: ' + e.message['desc'])
        assert False

    #
    # Check that the MMR plugin was updated
    #
    try:
        entry = topology_m2.ms["master1"].search_s(MMR_PLUGIN, ldap.SCOPE_BASE,
                                                   'objectclass=*')
        if not entry[0].hasValue('nsslapd-plugin-depends-on-named', 'AES'):
            log.fatal('The MMR Plugin was not correctly updated')
            assert False
        else:
            log.info('The MMR plugin was correctly updated')
    except ldap.LDAPError as e:
        log.fatal('Failed to find AES plugin: ' + e.message['desc'])
        assert False

    #
    # Check that the DES plugin was correctly updated
    #
    try:
        entry = topology_m2.ms["master1"].search_s(DES_PLUGIN, ldap.SCOPE_BASE,
                                                   'objectclass=*')
        if not entry[0].hasValue('nsslapd-pluginPath', 'libpbe-plugin'):
            log.fatal('The DES Plugin was not correctly updated')
            assert False
        else:
            log.info('The DES plugin was correctly updated')
    except ldap.LDAPError as e:
        log.fatal('Failed to find AES plugin: ' + e.message['desc'])
        assert False

    #
    # Check replication one last time
    #
    try:
        topology_m2.ms["master1"].add_s(
            Entry((USER_DN, {
                'objectclass': "top person".split(),
                'sn': 'sn',
                'cn': 'test_user'
            })))
        loop = 0
        ent = None
        while loop <= 10:
            try:
                ent = topology_m2.ms["master2"].getEntry(
                    USER_DN, ldap.SCOPE_BASE, "(objectclass=*)")
                break
            except ldap.NO_SUCH_OBJECT:
                time.sleep(1)
                loop += 1
        if not ent:
            log.fatal('Replication test failed!')
            assert False
        else:
            log.info('Replication test passed')
    except ldap.LDAPError as e:
        log.fatal('Failed to add test user: '******'desc'])
        assert False

    # Check the entry
    log.info('Entry before running task...')
    try:
        entry = topology_m2.ms["master1"].search_s(USER1_DN, ldap.SCOPE_BASE,
                                                   'objectclass=*')
        if entry:
            print(str(entry))
        else:
            log.fatal('Failed to find entries')
            assert False
    except ldap.LDAPError as e:
        log.fatal('Failed to search for entries: ' + e.message['desc'])
        assert False

    #
    # Test the DES2AES Task on USER1_DN
    #
    try:
        topology_m2.ms["master1"].add_s(
            Entry((DES2AES_TASK_DN, {
                'objectclass': ['top', 'extensibleObject'],
                'suffix': DEFAULT_SUFFIX,
                'cn': 'convert'
            })))
    except ldap.LDAPError as e:
        log.fatal('Failed to add task entry: ' + e.message['desc'])
        assert False

    # Wait for task
    task_entry = Entry(DES2AES_TASK_DN)
    (done,
     exitCode) = topology_m2.ms["master1"].tasks.checkTask(task_entry, True)
    if exitCode:
        log.fatal("Error: des2aes task exited with %d" % (exitCode))
        assert False

    # Check the entry
    try:
        entry = topology_m2.ms["master1"].search_s(USER1_DN, ldap.SCOPE_BASE,
                                                   'objectclass=*')
        if entry:
            val = entry[0].getValue('description')
            print(str(entry[0]))
            if val.startswith('{AES-'):
                log.info('Task: DES credentials have been converted to AES')
            else:
                log.fatal('Task: Failed to convert credentials from DES to ' +
                          'AES! (%s)' % (val))
                assert False
        else:
            log.fatal('Failed to find entries')
            assert False
    except ldap.LDAPError as e:
        log.fatal('Failed to search for entries: ' + e.message['desc'])
        assert False
Exemplo n.º 42
0
    def reindex(self, suffix=None, benamebase=None, attrname=None, args=None):
        '''
        Reindex a 'suffix' (or 'benamebase' that stores that suffix) for a given 'attrname'.
        It uses an internal task to acheive this request.

        If 'suffix' and 'benamebase' are specified, it uses 'benamebase' first else 'suffix'.
        If both 'suffix' and 'benamebase' are missing it raise ValueError

        @param suffix - suffix of the backend
        @param benamebase - 'commonname'/'cn' of the backend (e.g. 'userRoot')
        @param attrname - attribute name
        @param args - is a dictionary that contains modifier of the reindex task
                wait: True/[False] - If True, 'index' waits for the completion of the task before to return

        @return None

        @raise ValueError if invalid missing benamebase and suffix or invalid benamebase

        '''
        if not benamebase and not suffix:
            raise ValueError("Specify either bename or suffix")

        # If backend name was provided, retrieve the suffix
        if benamebase:
            ents = self.conn.mappingtree.list(bename=benamebase)
            if len(ents) != 1:
                raise ValueError("invalid backend name: %s" % benamebase)

            attr_suffix = MT_PROPNAME_TO_ATTRNAME[MT_SUFFIX]
            if not ents[0].hasAttr(attr_suffix):
                raise ValueError("invalid backend name: %s, or entry without %s" % (benamebase, attr_suffix))

            suffix = ents[0].getValue(attr_suffix)

        entries_backend = self.conn.backend.list(suffix=suffix)
        cn = "index_%s_%s" % (attrname, time.strftime("%m%d%Y_%H%M%S", time.localtime()))
        dn = "cn=%s,%s" % (cn, DN_INDEX_TASK)
        entry = Entry(dn)
        entry.update({
            'objectclass': ['top', 'extensibleObject'],
            'cn': cn,
            'nsIndexAttribute': attrname,
            'nsInstance': entries_backend[0].cn
        })
        # assume 1 local backend

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add the index task for %s" % attrname)
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: index task %s exited with %d" % (
                    cn, exitCode))
        else:
            self.log.info("Index task %s completed successfully" % (
                    cn))
        return exitCode
Exemplo n.º 43
0
m2 = tools.DirSrvTools.createInstance(createargs)
#del os.environ['USE_DBX']
m2.replicaSetupAll(m2replargs)

print "create agreements and init consumers"
agmtm1tom2 = m1.agreement.create(basedn, m2.host, m2.port, agmtargs)
m1.replica.start_and_wait(agmtm1tom2)
agmtm2tom1 = m2.agreement.create(basedn, m1.host, m1.port, agmtargs)

nents = 5
m1ents = range(nents)
m2ents = range(len(m1ents), len(m1ents)+nents+1)
print "Add %d entries to m2" % len(m2ents)
for ii in m2ents:
    dn = "cn=%d, %s" % (ii, basedn)
    ent = Entry(dn)
    ent.setValues('objectclass', 'person')
    ent.setValues('sn', 'testuser')
    m2.add_s(ent)
    print "Added m2 entry", dn

print "Add %d entries to m1" % len(m1ents)
for ii in m1ents:
    dn = "cn=%d, %s" % (ii, basedn)
    ent = Entry(dn)
    ent.setValues('objectclass', 'person')
    ent.setValues('sn', 'testuser')
    m1.add_s(ent)
    print "Added m1 entry", dn

print "Sleep for 5 seconds to let changes propagate . . ."
Exemplo n.º 44
0
    def importLDIF(self, suffix=None, benamebase=None, input_file=None, args=None):
        '''
        Import from a LDIF format a given 'suffix' (or 'benamebase' that stores that suffix).
        It uses an internal task to acheive this request.

        If 'suffix' and 'benamebase' are specified, it uses 'benamebase' first else 'suffix'.
        If both 'suffix' and 'benamebase' are missing it raise ValueError

        'input_file' is the ldif input file

        @param suffix - suffix of the backend
        @param benamebase - 'commonname'/'cn' of the backend (e.g. 'userRoot')
        @param ldif_input - file that will contain the entries in LDIF format, to import
        @param args - is a dictionary that contains modifier of the import task
                wait: True/[False] - If True, 'export' waits for the completion of the task before to return

        @return None

        @raise ValueError

        '''
        # Checking the parameters
        if not benamebase and not suffix:
            raise ValueError("Specify either bename or suffix")

        if not input_file:
            raise ValueError("input_file is mandatory")

        if not os.path.exists(input_file):
            raise ValueError("Import file (%s) does not exist" % input_file)

        # Prepare the task entry
        cn = "import_" + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = "cn=%s,%s" % (cn, DN_IMPORT_TASK)
        entry = Entry(dn)
        entry.setValues('objectclass', 'top', 'extensibleObject')
        entry.setValues('cn', cn)
        entry.setValues('nsFilename', input_file)
        if benamebase:
            entry.setValues('nsInstance', benamebase)
        else:
            entry.setValues('nsIncludeSuffix', suffix)

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add the import task of %s" % input_file)
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: import task %s for file %s exited with %d" % (
                    cn, input_file, exitCode))
        else:
            self.log.info("Import task %s for file %s completed successfully" % (
                    cn, input_file))
        return exitCode
Exemplo n.º 45
0
    def test_update_complex(self):
        # compare two entries created with different methods
        nsuffix, replid, replicatype = ("dc=example,dc=com", 5,
                                        lib389.REPLICA_RDWR_TYPE)
        binddnlist, legacy = ['uid=pippo, cn=config'], 'off'
        dn = "dc=example,dc=com"
        entry = Entry(dn)
        entry.setValues(
            'objectclass', "top", "nsds5replica", "extensibleobject")
        entry.setValues('cn', "replica")
        entry.setValues('nsds5replicaroot', nsuffix)
        entry.setValues('nsds5replicaid', str(replid))
        entry.setValues('nsds5replicatype', str(replicatype))
        entry.setValues('nsds5flags', "1")
        entry.setValues('nsds5replicabinddn', binddnlist)
        entry.setValues('nsds5replicalegacyconsumer', legacy)

        uentry = Entry((
            dn, {'objectclass': ["top", "nsds5replica", "extensibleobject"],
                 'cn': ["replica"]})
        )
        log.debug("Entry created with dict:", uentry)
        # Entry.update *replaces*, so be careful with multi-valued attrs
        uentry.update({
            'nsds5replicaroot': nsuffix,
            'nsds5replicaid': str(replid),
            'nsds5replicatype': str(replicatype),
            'nsds5flags': '1',
            'nsds5replicabinddn': binddnlist,
            'nsds5replicalegacyconsumer': legacy
        })
        uentry_s, entry_s = list(map(str, (uentry, entry)))
        assert uentry_s == entry_s, "Mismatching entries [%r] vs [%r]" % (
            uentry, entry)
Exemplo n.º 46
0
def test_selfdn_permission_add(topology_st, allow_user_init):
    """Check add entry operation with and without SelfDN aci

    :id: e837a9ef-be92-48da-ad8b-ebf42b0fede1
    :setup: Standalone instance, add a entry which is used to bind,
    enable acl error logging by setting 'nsslapd-errorlog-level' to '128',
    remove aci's to start with a clean slate, and add dummy entries
    :steps:
        1. Check we can not ADD an entry without the proper SELFDN aci
        2. Check with the proper ACI we can not ADD with 'member' attribute
        3. Check entry to add with memberS and with the ACI
        4. Check with the proper ACI and 'member' it succeeds to ADD
    :expectedresults:
        1. Operation should be successful
        2. Operation should be successful
        3. Operation should fail with Insufficient Access
        4. Operation should be successful
     """
    topology_st.standalone.log.info(
        "\n\n######################### ADD ######################\n")

    # bind as bind_entry
    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)

    # Prepare the entry with multivalued members
    entry_with_members = Entry(ENTRY_DN)
    entry_with_members.setValues('objectclass', 'top', 'person',
                                 'OCticket47653')
    entry_with_members.setValues('sn', ENTRY_NAME)
    entry_with_members.setValues('cn', ENTRY_NAME)
    entry_with_members.setValues('postalAddress', 'here')
    entry_with_members.setValues('postalCode', '1234')
    members = []
    for cpt in range(MAX_OTHERS):
        name = "%s%d" % (OTHER_NAME, cpt)
        members.append("cn=%s,%s" % (name, SUFFIX))
    members.append(BIND_DN)
    entry_with_members.setValues('member', members)

    # Prepare the entry with one member
    entry_with_member = Entry(ENTRY_DN)
    entry_with_member.setValues('objectclass', 'top', 'person',
                                'OCticket47653')
    entry_with_member.setValues('sn', ENTRY_NAME)
    entry_with_member.setValues('cn', ENTRY_NAME)
    entry_with_member.setValues('postalAddress', 'here')
    entry_with_member.setValues('postalCode', '1234')
    member = []
    member.append(BIND_DN)
    entry_with_member.setValues('member', member)

    # entry to add WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
    try:
        topology_st.standalone.log.info(
            "Try to add Add  %s (aci is missing): %r" %
            (ENTRY_DN, entry_with_member))

        topology_st.standalone.add_s(entry_with_member)
    except Exception as e:
        topology_st.standalone.log.info("Exception (expected): %s" %
                                        type(e).__name__)
        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)

    # Ok Now add the proper ACI
    topology_st.standalone.log.info("Bind as %s and add the ADD SELFDN aci" %
                                    DN_DM)
    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)

    ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
    ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
    ACI_ALLOW = "(version 3.0; acl \"SelfDN add\"; allow (add)"
    ACI_SUBJECT = " userattr = \"member#selfDN\";)"
    ACI_BODY = ACI_TARGET + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
    mod = [(ldap.MOD_ADD, 'aci', ensure_bytes(ACI_BODY))]
    topology_st.standalone.modify_s(SUFFIX, mod)

    # bind as bind_entry
    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)

    # entry to add WITHOUT member and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
    try:
        topology_st.standalone.log.info(
            "Try to add Add  %s (member is missing)" % ENTRY_DN)
        topology_st.standalone.add_s(
            Entry((ENTRY_DN, {
                'objectclass': ENTRY_OC.split(),
                'sn': ENTRY_NAME,
                'cn': ENTRY_NAME,
                'postalAddress': 'here',
                'postalCode': '1234'
            })))
    except Exception as e:
        topology_st.standalone.log.info("Exception (expected): %s" %
                                        type(e).__name__)
        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)

    # entry to add WITH memberS and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
    # member should contain only one value
    try:
        topology_st.standalone.log.info(
            "Try to add Add  %s (with several member values)" % ENTRY_DN)
        topology_st.standalone.add_s(entry_with_members)
    except Exception as e:
        topology_st.standalone.log.info("Exception (expected): %s" %
                                        type(e).__name__)
        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)

    topology_st.standalone.log.info("Try to add Add  %s should be successful" %
                                    ENTRY_DN)
    topology_st.standalone.add_s(entry_with_member)
Exemplo n.º 47
0
    def create(self, suffix=None, bename=None, parent=None):
        '''
            Create a mapping tree entry (under "cn=mapping tree,cn=config"), for the 'suffix' 
            and that is stored in 'bename' backend. 
            'bename' backend must exists before creating the mapping tree entry. 
            
            If a 'parent' is provided that means that we are creating a sub-suffix mapping tree.

            @param suffix - suffix mapped by this mapping tree entry. It will be the common name ('cn') of the entry
            @param benamebase - backend common name (e.g. 'userRoot')
            @param parent - if provided is a parent suffix of 'suffix'
            
            @return DN of the mapping tree entry
            
            @raise ldap.NO_SUCH_OBJECT - if the backend entry or parent mapping tree does not exist

        '''
        # Check suffix is provided
        if not suffix:
            raise ValueError("suffix is mandatory")
        else:
            nsuffix = normalizeDN(suffix)
        
        # Check backend name is provided
        if not bename:
            raise ValueError("backend name is mandatory")
        
        # Check that if the parent suffix is provided then
        # it exists a mapping tree for it
        if parent:
            nparent = normalizeDN(parent)
            filt = suffixfilt(parent)
            try:
                entry = self.conn.getEntry(DN_MAPPING_TREE, ldap.SCOPE_SUBTREE, filt)
                pass
            except NoSuchEntryError:
                raise ValueError("parent suffix has no mapping tree")
        else:
            nparent = ""
            
        # Check if suffix exists, return
        filt = suffixfilt(suffix)
        try:
            entry = self.conn.getEntry(DN_MAPPING_TREE, ldap.SCOPE_SUBTREE, filt)
            return entry
        except NoSuchEntryError:
            entry = None

        # 
        # Now start the real work
        #
        
        # fix me when we can actually used escaped DNs
        dn = ','.join(('cn="%s"' % nsuffix, DN_MAPPING_TREE))
        entry = Entry(dn)
        entry.update({
            'objectclass': ['top', 'extensibleObject', MT_OBJECTCLASS_VALUE],
            'nsslapd-state': 'backend',
            # the value in the dn has to be DN escaped
            # internal code will add the quoted value - unquoted value is useful for searching
            MT_PROPNAME_TO_ATTRNAME[MT_SUFFIX]: nsuffix,
            MT_PROPNAME_TO_ATTRNAME[MT_BACKEND]: bename
        })
        
        # possibly add the parent
        if parent:
            entry.setValues(MT_PROPNAME_TO_ATTRNAME[MT_PARENT_SUFFIX], nparent)
            
        try:
            self.log.debug("Creating entry: %s" % entry.dn)
            self.log.info("Entry %r" % entry)
            self.conn.add_s(entry)
        except ldap.LDAPError, e:
            raise ldap.LDAPError("Error adding suffix entry " + dn, e)
Exemplo n.º 48
0
def test_48294_init(topology_st):
    """
    Set up Linked Attribute
    """
    _header(
        topology_st,
        'Testing Ticket 48294 - Linked Attributes plug-in - won\'t update links after MODRDN operation'
    )

    log.info('Enable Dynamic plugins, and the linked Attrs plugin')
    try:
        topology_st.standalone.modify_s(
            DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-dynamic-plugins', 'on')])
    except ldap.LDAPError as e:
        log.fatal('Failed to enable dynamic plugin!' + e.message['desc'])
        assert False

    try:
        topology_st.standalone.plugins.enable(name=PLUGIN_LINKED_ATTRS)
    except ValueError as e:
        log.fatal('Failed to enable linked attributes plugin!' +
                  e.message['desc'])
        assert False

    log.info('Add the plugin config entry')
    try:
        topology_st.standalone.add_s(
            Entry((MANAGER_LINK, {
                'objectclass': 'top extensibleObject'.split(),
                'cn': 'Manager Link',
                'linkType': LINKTYPE,
                'managedType': MANAGEDTYPE
            })))
    except ldap.LDAPError as e:
        log.fatal('Failed to add linked attr config entry: error ' +
                  e.message['desc'])
        assert False

    log.info('Add 2 entries: manager1 and employee1')
    try:
        topology_st.standalone.add_s(
            Entry(('uid=manager1,%s' % OU_PEOPLE, {
                'objectclass': 'top extensibleObject'.split(),
                'uid': 'manager1'
            })))
    except ldap.LDAPError as e:
        log.fatal('Add manager1 failed: error ' + e.message['desc'])
        assert False

    try:
        topology_st.standalone.add_s(
            Entry(('uid=employee1,%s' % OU_PEOPLE, {
                'objectclass': 'top extensibleObject'.split(),
                'uid': 'employee1'
            })))
    except ldap.LDAPError as e:
        log.fatal('Add employee1 failed: error ' + e.message['desc'])
        assert False

    log.info('Add linktype to manager1')
    topology_st.standalone.modify_s(
        'uid=manager1,%s' % OU_PEOPLE,
        [(ldap.MOD_ADD, LINKTYPE, 'uid=employee1,%s' % OU_PEOPLE)])

    log.info('Check managed attribute')
    check_attr_val(topology_st, 'uid=employee1,%s' % OU_PEOPLE, MANAGEDTYPE,
                   'uid=manager1,%s' % OU_PEOPLE)

    log.info('PASSED')
Exemplo n.º 49
0
def test_create(topology):
    """This test creates
         - suffix/backend (NEW_SUFFIX_[12], NEW_BACKEND_[12]) : Master
         - suffix/backend (NEW_SUFFIX_[12], NEW_BACKEND_[12]) : Consumer
         - replica NEW_SUFFIX_1 as MASTER : Master
         - replica NEW_SUFFIX_2 as CONSUMER : Master
    """

    log.info("\n\n##########\n### CREATE\n############")
    #
    # MASTER (suffix/backend)
    #
    backendEntry = topology.master.backend.create(
        suffix=NEW_SUFFIX_1, properties={BACKEND_NAME: NEW_BACKEND_1})
    backendEntry = topology.master.backend.create(
        suffix=NEW_SUFFIX_2, properties={BACKEND_NAME: NEW_BACKEND_2})

    ents = topology.master.mappingtree.list()
    master_nb_mappingtree = len(ents)

    # create a first additional mapping tree
    topology.master.mappingtree.create(NEW_SUFFIX_1, bename=NEW_BACKEND_1)
    ents = topology.master.mappingtree.list()
    assert len(ents) == (master_nb_mappingtree + 1)
    topology.master.add_s(
        Entry((NEW_SUFFIX_1, {
            'objectclass': "top organizationalunit".split(),
            'ou': NEW_SUFFIX_1.split('=', 1)[1]
        })))

    # create a second additional mapping tree
    topology.master.mappingtree.create(NEW_SUFFIX_2, bename=NEW_BACKEND_2)
    ents = topology.master.mappingtree.list()
    assert len(ents) == (master_nb_mappingtree + 2)
    topology.master.add_s(
        Entry((NEW_SUFFIX_2, {
            'objectclass': "top organizationalunit".split(),
            'ou': NEW_SUFFIX_2.split('=', 1)[1]
        })))
    log.info('Master it exists now %d suffix(es)' % len(ents))

    #
    # CONSUMER (suffix/backend)
    #
    backendEntry = topology.consumer.backend.create(
        suffix=NEW_SUFFIX_1, properties={BACKEND_NAME: NEW_BACKEND_1})
    backendEntry = topology.consumer.backend.create(
        suffix=NEW_SUFFIX_2, properties={BACKEND_NAME: NEW_BACKEND_2})

    ents = topology.consumer.mappingtree.list()
    consumer_nb_mappingtree = len(ents)

    # create a first additional mapping tree
    topology.consumer.mappingtree.create(NEW_SUFFIX_1, bename=NEW_BACKEND_1)
    ents = topology.consumer.mappingtree.list()
    assert len(ents) == (consumer_nb_mappingtree + 1)
    topology.consumer.add_s(
        Entry((NEW_SUFFIX_1, {
            'objectclass': "top organizationalunit".split(),
            'ou': NEW_SUFFIX_1.split('=', 1)[1]
        })))

    # create a second additional mapping tree
    topology.consumer.mappingtree.create(NEW_SUFFIX_2, bename=NEW_BACKEND_2)
    ents = topology.consumer.mappingtree.list()
    assert len(ents) == (consumer_nb_mappingtree + 2)
    topology.consumer.add_s(
        Entry((NEW_SUFFIX_2, {
            'objectclass': "top organizationalunit".split(),
            'ou': NEW_SUFFIX_2.split('=', 1)[1]
        })))
    log.info('Consumer it exists now %d suffix(es)' % len(ents))

    #
    # Now create REPLICAS on master
    #
    # check it exists this entry to stores the changelogs
    topology.master.changelog.create()

    # create a master
    topology.master.replica.create(suffix=NEW_SUFFIX_1,
                                   role=ReplicaRole.MASTER,
                                   rid=1)
    ents = topology.master.replica.list()
    assert len(ents) == 1
    log.info('Master replica %s' % ents[0].dn)

    # create a consumer
    topology.master.replica.create(suffix=NEW_SUFFIX_2,
                                   role=ReplicaRole.CONSUMER)
    ents = topology.master.replica.list()
    assert len(ents) == 2
    ents = topology.master.replica.list(suffix=NEW_SUFFIX_2)
    log.info('Consumer replica %s' % ents[0].dn)

    #
    # Now create REPLICAS on consumer
    #
    # create a master
    topology.consumer.replica.create(suffix=NEW_SUFFIX_1,
                                     role=ReplicaRole.CONSUMER)
    ents = topology.consumer.replica.list()
    assert len(ents) == 1
    log.info('Consumer replica %s' % ents[0].dn)

    # create a consumer
    topology.consumer.replica.create(suffix=NEW_SUFFIX_2,
                                     role=ReplicaRole.CONSUMER)
    ents = topology.consumer.replica.list()
    assert len(ents) == 2
    ents = topology.consumer.replica.list(suffix=NEW_SUFFIX_2)
    log.info('Consumer replica %s' % ents[0].dn)
Exemplo n.º 50
0
def test_reliab7_5_run(topology):
    '''
    Starting issuing adds, deletes, mods, modrdns, and searches
    '''
    global RUNNING
    count = 1
    RUNNING = True

    # Start some searches to run through the entire stress test
    fullSearch1 = DoFullSearches(topology.supplier1)
    fullSearch1.start()
    fullSearch2 = DoFullSearches(topology.supplier2)
    fullSearch2.start()

    while count <= MAX_PASSES:
        log.info('################## Reliabilty 7.5 Pass: %d' % count)

        # Supplier 1
        add_del_users1 = AddDelUsers(topology.supplier1, '1')
        add_del_users1.start()
        mod_users1 = ModUsers(topology.supplier1, '1')
        mod_users1.start()
        search1 = DoSearches(topology.supplier1, '1')
        search1.start()

        # Supplier 2
        add_del_users2 = AddDelUsers(topology.supplier2, '2')
        add_del_users2.start()
        mod_users2 = ModUsers(topology.supplier2, '2')
        mod_users2.start()
        search2 = DoSearches(topology.supplier2, '2')
        search2.start()

        # Search the suppliers
        search3 = DoSearches(topology.supplier1, '1')
        search3.start()
        search4 = DoSearches(topology.supplier2, '2')
        search4.start()

        # Wait for threads to finish
        log.info('################## Waiting for threads to finish...')
        add_del_users1.join()
        mod_users1.join()
        add_del_users2.join()
        mod_users2.join()
        log.info('################## Update threads finished.')
        search1.join()
        search2.join()
        search3.join()
        search4.join()
        log.info('################## All threads finished.')

        # Allow some time for replication to catch up before firing
        # off the next round of updates
        time.sleep(5)
        count += 1

    #
    # Wait for replication to converge
    #
    if CHECK_CONVERGENCE:
        # Add an entry to each supplier, and wait for it to replicate
        SUPPLIER1_DN = 'uid=rel7.5-supplier1,' + DEFAULT_SUFFIX
        SUPPLIER2_DN = 'uid=rel7.5-supplier2,' + DEFAULT_SUFFIX

        # Supplier 1
        try:
            topology.supplier1.add_s(
                Entry((SUPPLIER1_DN, {
                    'objectclass': ['top', 'extensibleObject'],
                    'sn': '1',
                    'cn': 'user 1',
                    'uid': 'rel7.5-supplier1',
                    'userpassword': PASSWORD
                })))
        except ldap.LDAPError as e:
            log.fatal('Failed to add replication test entry ' + SUPPLIER1_DN +
                      ': error ' + e.message['desc'])
            assert False

        log.info('################## Waiting for supplier 2 to converge...')

        while True:
            entry = None
            try:
                entry = topology.supplier2.search_s(SUPPLIER1_DN,
                                                    ldap.SCOPE_BASE,
                                                    'objectclass=*')
            except ldap.NO_SUCH_OBJECT:
                pass
            except ldap.LDAPError as e:
                log.fatal('Search Users: Search failed (%s): %s' %
                          (SUPPLIER1_DN, e.message['desc']))
                assert False
            if entry:
                break
            time.sleep(5)

        log.info('################## Supplier 2 converged.')

        # Supplier 2
        try:
            topology.supplier2.add_s(
                Entry((SUPPLIER2_DN, {
                    'objectclass': ['top', 'extensibleObject'],
                    'sn': '1',
                    'cn': 'user 1',
                    'uid': 'rel7.5-supplier2',
                    'userpassword': PASSWORD
                })))
        except ldap.LDAPError as e:
            log.fatal('Failed to add replication test entry ' + SUPPLIER1_DN +
                      ': error ' + e.message['desc'])
            assert False

        log.info('################## Waiting for supplier 1 to converge...')
        while True:
            entry = None
            try:
                entry = topology.supplier1.search_s(SUPPLIER2_DN,
                                                    ldap.SCOPE_BASE,
                                                    'objectclass=*')
            except ldap.NO_SUCH_OBJECT:
                pass
            except ldap.LDAPError as e:
                log.fatal('Search Users: Search failed (%s): %s' %
                          (SUPPLIER2_DN, e.message['desc']))
                assert False
            if entry:
                break
            time.sleep(5)

        log.info('################## Supplier 1 converged.')

    # Stop the full searches
    RUNNING = False
    fullSearch1.join()
    fullSearch2.join()
Exemplo n.º 51
0
    def fixupMemberOf(self, suffix=None, benamebase=None, filt=None, args=None):
        '''
            Trigger a fixup task on 'suffix' (or 'benamebase' that stores that suffix) related to the
            entries 'memberof' of groups. It uses an internal task to acheive this request.

            If 'suffix' and 'benamebase' are specified, it uses 'benamebase' first else 'suffix'.
            If both 'suffix' and 'benamebase' are missing it raise ValueError

            'filt' is a filter that will select all the entries (under 'suffix') that we need to evaluate/fix.
            If missing, the default value is "(|(objectclass=inetuser)(objectclass=inetadmin))"

            @param suffix - suffix of the backend
            @param benamebase - 'commonname'/'cn' of the backend (e.g. 'userRoot')
            @param args - is a dictionary that contains modifier of the fixupMemberOf task
                wait: True/[False] - If True,  waits for the completion of the task before to return

            @return exit code

            @raise ValueError: if benamebase and suffix are specified, or can not retrieve the suffix from the
                            mapping tree entry
        '''
        if not benamebase and not suffix:
            raise ValueError("Specify either bename or suffix")

        # If backend name was provided, retrieve the suffix
        if benamebase:
            ents = self.conn.mappingtree.list(bename=benamebase)
            if len(ents) != 1:
                raise ValueError("invalid backend name: %s" % benamebase)

            attr = MT_PROPNAME_TO_ATTRNAME[MT_SUFFIX]
            if not ents[0].hasAttr(attr):
                raise ValueError("invalid backend name: %s, or entry without %s" % (benamebase, attr))

            suffix = ents[0].getValue(attr)

        cn = "fixupmemberof_" + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = "cn=%s,%s" % (cn, DN_MBO_TASK)
        entry = Entry(dn)
        entry.setValues('objectclass', 'top', 'extensibleObject')
        entry.setValues('cn', cn)
        entry.setValues('basedn', suffix)
        if filt:
            entry.setValues('filter', filt)

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add the memberOf fixup task")
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: fixupMemberOf task %s for basedn %s exited with %d" % (cn, suffix, exitCode))
        else:
            self.log.info("fixupMemberOf task %s for basedn %s completed successfully" % (cn, suffix))
        return exitCode
Exemplo n.º 52
0
def test_enableReplication(topology):
    """It checks
         - Ability to enable replication on a supplier
         - Ability to enable replication on a consumer
         - Failure to enable replication with wrong replicaID on supplier
         - Failure to enable replication with wrong replicaID on consumer
    """

    log.info("\n\n############\n### ENABLEREPLICATION\n##########")
    #
    # MASTER (suffix/backend)
    #
    backendEntry = topology.master.backend.create(
        suffix=NEW_SUFFIX_3, properties={BACKEND_NAME: NEW_BACKEND_3})

    ents = topology.master.mappingtree.list()
    master_nb_mappingtree = len(ents)

    # create a first additional mapping tree
    topology.master.mappingtree.create(NEW_SUFFIX_3, bename=NEW_BACKEND_3)
    ents = topology.master.mappingtree.list()
    assert len(ents) == (master_nb_mappingtree + 1)
    topology.master.add_s(
        Entry((NEW_SUFFIX_3, {
            'objectclass': "top organizationalunit".split(),
            'ou': NEW_SUFFIX_3.split('=', 1)[1]
        })))

    # a supplier should have replicaId in [1..CONSUMER_REPLICAID[
    with pytest.raises(ValueError) as excinfo:
        topology.master.replica.enableReplication(suffix=NEW_SUFFIX_3,
                                                  role=ReplicaRole.MASTER,
                                                  replicaId=CONSUMER_REPLICAID)
    log.info("Exception (expected): %s" % str(excinfo.value))
    topology.master.replica.enableReplication(suffix=NEW_SUFFIX_3,
                                              role=ReplicaRole.MASTER,
                                              replicaId=1)

    #
    # MASTER (suffix/backend)
    #
    backendEntry = topology.master.backend.create(
        suffix=NEW_SUFFIX_4, properties={BACKEND_NAME: NEW_BACKEND_4})

    ents = topology.master.mappingtree.list()
    master_nb_mappingtree = len(ents)

    # create a first additional mapping tree
    topology.master.mappingtree.create(NEW_SUFFIX_4, bename=NEW_BACKEND_4)
    ents = topology.master.mappingtree.list()
    assert len(ents) == (master_nb_mappingtree + 1)
    topology.master.add_s(
        Entry((NEW_SUFFIX_4, {
            'objectclass': "top organizationalunit".split(),
            'ou': NEW_SUFFIX_4.split('=', 1)[1]
        })))

    # A consumer should have CONSUMER_REPLICAID not '1'
    with pytest.raises(ValueError) as excinfo:
        topology.master.replica.enableReplication(suffix=NEW_SUFFIX_4,
                                                  role=ReplicaRole.CONSUMER,
                                                  replicaId=1)
    log.info("Exception (expected): %s" % str(excinfo.value))
    topology.master.replica.enableReplication(suffix=NEW_SUFFIX_4,
                                              role=ReplicaRole.CONSUMER)
Exemplo n.º 53
0
    def automemberExport(self, suffix=DEFAULT_SUFFIX, scope='sub', fstr='objectclass=top',
                          ldif_out=None, args=None):
        '''
        @param suffix - The suffix the task should examine - default is "dc=example,dc=com"
        @param scope - The scope of the search to find entries
        @param fstr - The search filter to find entries
        @param ldif_out - The name for the output LDIF file
        @param args - is a dictionary that contains modifier of the task
                wait: True/[False] - If True,  waits for the completion of the task before to return
        @return exit code
        @raise ValueError: if ldif_out is not provided
        '''

        if not ldif_out:
            raise ValueError("Missing ldif_out")

        cn = 'task-' + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = ('cn=%s,cn=automember export updates,cn=tasks,cn=config' % cn)
        entry = Entry(dn)
        entry.setValues('objectclass', 'top', 'extensibleObject')
        entry.setValues('cn', cn)
        entry.setValues('basedn', suffix)
        entry.setValues('filter', fstr)
        entry.setValues('scope', scope)
        entry.setValues('ldif', ldif_out)

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add Automember Export Updates task")
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: Automember Export Updates task (%s) exited with %d" % (cn, exitCode))
        else:
            self.log.info("Automember Export Updates task (%s) completed successfully" % (cn))
        return exitCode
Exemplo n.º 54
0
 def test_init_badstr(self):
     # This should not be allowed
     e = Entry('no equal sign here')
Exemplo n.º 55
0
def test_entrycache_on_modrdn_failure(topology_st):
    """This test checks that when a modrdn fails, the destination entry is not returned by a search
    This could happen in case the destination entry remains in the entry cache

    :id: a4d8ac0b-2448-406a-9dc2-5a72851e30b6
    :setup: Standalone Instance
    :steps:
        1. configure memberof to only scope ou=people,SUFFIX
        2. Creates 10 users
        3. Create groups0 (in peoplebase) that contain user0 and user1
        4. Check user0 and user1 have memberof=group0.dn
        5. Create group1 (OUT peoplebase) that contain user0 and user1
        6. Check user0 and user1 have NOT memberof=group1.dn
        7. Move group1 IN peoplebase and check users0 and user1 HAVE memberof=group1.dn
        8. Create group2 (OUT peoplebase) that contain user2 and user3. Group2 contains a specific description value
        9. Check user2 and user3 have NOT memberof=group2.dn
        10. configure memberof so that added objectclass does not allow 'memberof' attribute
        11. Move group2 IN peoplebase and check move failed OPERATIONS_ERROR (because memberof failed)
        12. Search all groups and check that the group, having the specific description value,
            has the original DN of group2.dn
    :expectedresults:
        1. should succeed
        2. should succeed
        3. should succeed
        4. should succeed
        5. should succeed
        6. should succeed
        7. should succeed
        8. should succeed
        9. should succeed
        10. should succeed
        11. should fail OPERATION_ERROR because memberof plugin fails to add 'memberof' to members.
        12. should succeed

    """

    # only scopes peoplebase
    _config_memberof_entrycache_on_modrdn_failure(topology_st.standalone)
    topology_st.standalone.restart(timeout=10)

    # create 10 users
    peoplebase = 'ou=people,%s' % SUFFIX
    for i in range(10):
        cn = 'user%d' % i
        dn = 'cn=%s,%s' % (cn, peoplebase)
        log.fatal('Adding user (%s): ' % dn)
        topology_st.standalone.add_s(
            Entry((dn, {
                'objectclass': ['top', 'person'],
                'sn': 'user_%s' % cn,
                'description': 'add on standalone'
            })))

    # Check that members of group0 (in the scope) have 'memberof
    group0_dn = 'cn=group_in0,%s' % peoplebase
    topology_st.standalone.add_s(
        Entry((group0_dn, {
            'objectclass': ['top', 'groupofnames'],
            'member': [
                'cn=user0,%s' % peoplebase,
                'cn=user1,%s' % peoplebase,
            ],
            'description':
            'mygroup'
        })))

    # Check the those entries have memberof with group0
    for i in range(2):
        user_dn = 'cn=user%d,%s' % (i, peoplebase)
        ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE,
                                              "(objectclass=*)", ['memberof'])
        assert ent.hasAttr('memberof')
        found = False
        for val in ent.getValues('memberof'):
            topology_st.standalone.log.info(
                "!!!!!!! %s: memberof->%s (vs %s)" %
                (user_dn, val, group0_dn.encode().lower()))
            if val.lower() == group0_dn.encode().lower():
                found = True
                break
        assert found

    # Create a group1 out of the scope
    group1_dn = 'cn=group_out1,%s' % SUFFIX
    topology_st.standalone.add_s(
        Entry((group1_dn, {
            'objectclass': ['top', 'groupofnames'],
            'member': [
                'cn=user0,%s' % peoplebase,
                'cn=user1,%s' % peoplebase,
            ],
            'description':
            'mygroup'
        })))

    # Check the those entries have not memberof with group1
    for i in range(2):
        user_dn = 'cn=user%d,%s' % (i, peoplebase)
        ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE,
                                              "(objectclass=*)", ['memberof'])
        assert ent.hasAttr('memberof')
        found = False
        for val in ent.getValues('memberof'):
            topology_st.standalone.log.info(
                "!!!!!!! %s: memberof->%s (vs %s)" %
                (user_dn, val, group1_dn.encode().lower()))
            if val.lower() == group1_dn.encode().lower():
                found = True
                break
        assert not found

    # move group1 into the scope and check user0 and user1 are memberof group1
    topology_st.standalone.rename_s(group1_dn,
                                    'cn=group_in1',
                                    newsuperior=peoplebase,
                                    delold=0)
    new_group1_dn = 'cn=group_in1,%s' % peoplebase
    for i in range(2):
        user_dn = 'cn=user%d,%s' % (i, peoplebase)
        ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE,
                                              "(objectclass=*)", ['memberof'])
        assert ent.hasAttr('memberof')
        found = False
        for val in ent.getValues('memberof'):
            topology_st.standalone.log.info(
                "!!!!!!! %s: memberof->%s (vs %s)" %
                (user_dn, val, new_group1_dn.encode().lower()))
            if val.lower() == new_group1_dn.encode().lower():
                found = True
                break
        assert found

    # Create a group2 out of the scope with a SPECIFIC description value
    entry_description = "this is to check that the entry having this description has the appropriate DN"
    group2_dn = 'cn=group_out2,%s' % SUFFIX
    topology_st.standalone.add_s(
        Entry((group2_dn, {
            'objectclass': ['top', 'groupofnames'],
            'member': [
                'cn=user2,%s' % peoplebase,
                'cn=user3,%s' % peoplebase,
            ],
            'description':
            entry_description
        })))

    # Check the those entries have not memberof with group2
    for i in (2, 3):
        user_dn = 'cn=user%d,%s' % (i, peoplebase)
        ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE,
                                              "(objectclass=*)", ['memberof'])
        assert not ent.hasAttr('memberof')

    # memberof will not add the missing objectclass
    _disable_auto_oc_memberof(topology_st.standalone)
    topology_st.standalone.restart(timeout=10)

    # move group2 into the scope and check it fails
    try:
        topology_st.standalone.rename_s(group2_dn,
                                        'cn=group_in2',
                                        newsuperior=peoplebase,
                                        delold=0)
        topology_st.standalone.log.info(
            "This is unexpected, modrdn should fail as the member entry have not the appropriate objectclass"
        )
        assert False
    except ldap.OBJECT_CLASS_VIOLATION:
        pass

    # retrieve the entry having the specific description value
    # check that the entry DN is the original group2 DN
    ents = topology_st.standalone.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE,
                                           '(cn=gr*)')
    found = False
    for ent in ents:
        topology_st.standalone.log.info("retrieve: %s with desc=%s" %
                                        (ent.dn, ent.getValue('description')))
        if ent.getValue('description') == entry_description.encode():
            found = True
            assert ent.dn == group2_dn
    assert found
Exemplo n.º 56
0
    def create(self, suffix=None, role=None, rid=None, args=None):
        """
            Create a replica entry on an existing suffix.

            @param suffix - dn of suffix
            @param role   - REPLICAROLE_MASTER, REPLICAROLE_HUB or REPLICAROLE_CONSUMER
            @param rid    - number that identify the supplier replica (role=REPLICAROLE_MASTER) in the topology.
                            For hub/consumer (role=REPLICAROLE_HUB or REPLICAROLE_CONSUMER), rid value is not used.
                            This parameter is mandatory for supplier.

            @param args   - dictionnary of initial replica's properties
                Supported properties are:
                    REPLICA_SUFFIX
                    REPLICA_ID
                    REPLICA_TYPE
                    REPLICA_LEGACY_CONS    ['off']
                    REPLICA_BINDDN         [defaultProperties[REPLICATION_BIND_DN]]
                    REPLICA_PURGE_INTERVAL
                    REPLICA_PURGE_DELAY
                    REPLICA_PRECISE_PURGING
                    REPLICA_REFERRAL
                    REPLICA_FLAGS

            @return replica DN

            @raise InvalidArgumentError - if missing mandatory arguments
                   ValueError - argument with invalid value

        """
        # Check validity of role
        if not role:
            self.log.fatal(
                "Replica.create: replica role not specify (REPLICAROLE_*)")
            raise InvalidArgumentError("role missing")

        if not Replica._valid_role(role):
            self.log.fatal("enableReplication: replica role invalid (%s) " %
                           role)
            raise ValueError("invalid role: %s" % role)

        # check the validity of 'rid'
        if not Replica._valid_rid(role, rid=rid):
            self.log.fatal(
                "Replica.create: replica role is master but 'rid' is missing or invalid value"
            )
            raise InvalidArgumentError("rid missing or invalid value")

        # check the validity of the suffix
        if not suffix:
            self.log.fatal("Replica.create: suffix is missing")
            raise InvalidArgumentError("suffix missing")
        else:
            nsuffix = normalizeDN(suffix)

        # role is fine, set the replica type
        if role == REPLICAROLE_MASTER:
            rtype = REPLICA_RDWR_TYPE
        else:
            rtype = REPLICA_RDONLY_TYPE

        # Set the properties provided as mandatory parameter
        # The attribute name is not prefixed '+'/'-' => ldap.MOD_REPLACE
        properties = {
            REPLICA_SUFFIX: nsuffix,
            REPLICA_ID: str(rid),
            REPLICA_TYPE: str(rtype)
        }

        # If the properties in args are valid
        # add them to the 'properties' dictionary
        # The attribute name may be prefixed '+'/'-' => keep MOD type as provided in args
        if args:
            for prop in args:
                if not inProperties(prop, REPLICA_PROPNAME_TO_ATTRNAME):
                    raise ValueError("unknown property: %s" % prop)
                properties[prop] = args[prop]

        # Now set default values of unset properties
        Replica._set_or_default(REPLICA_LEGACY_CONS, properties, 'off')
        Replica._set_or_default(REPLICA_BINDDN, properties,
                                [defaultProperties[REPLICATION_BIND_DN]])

        if role != REPLICAROLE_CONSUMER:
            properties[REPLICA_FLAGS] = "1"

        # create replica entry in mapping-tree
        mtents = self.conn.mappingtree.list(suffix=nsuffix)
        mtent = mtents[0]
        dn_replica = ','.join((RDN_REPLICA, mtent.dn))
        try:
            entry = self.conn.getEntry(dn_replica, ldap.SCOPE_BASE)
            self.log.warn("Already setup replica for suffix %r" % nsuffix)
            self.conn.suffixes.setdefault(nsuffix, {})
            self.conn.replica.setProperties(replica_dn=dn_replica,
                                            properties=properties)
            return dn_replica
        except ldap.NO_SUCH_OBJECT:
            entry = None

        #
        # Now create the replica entry
        #
        entry = Entry(dn_replica)
        entry.setValues("objectclass", "top", REPLICA_OBJECTCLASS_VALUE,
                        "extensibleobject")
        self.conn.replica.setProperties(replica_entry=entry,
                                        properties=properties)
        self.conn.add_s(entry)

        # check if the entry exists TODO better to raise!
        self.conn._test_entry(dn_replica, ldap.SCOPE_BASE)

        self.conn.suffixes[nsuffix] = {'dn': dn_replica, 'type': rtype}
        return dn_replica
Exemplo n.º 57
0
    def usnTombstoneCleanup(self, suffix=DEFAULT_SUFFIX, bename=None, maxusn_to_delete=None, args=None):
        '''
        @param suffix - The suffix the task should cleanup - default is "dc=example,dc=com"
        @param backend - The 'backend' the task should cleanup
        @param maxusn_to_delete - Maximum number of usn's to delete
        @param args - is a dictionary that contains modifier of the task
                wait: True/[False] - If True,  waits for the completion of the task before to return
        @return exit code
        '''

        cn = 'task-' + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = ('cn=%s,cn=USN tombstone cleanup task,cn=tasks,cn=config' % cn)
        entry = Entry(dn)
        entry.setValues('objectclass', 'top', 'extensibleObject')
        entry.setValues('cn', cn)
        if not bename:
            entry.setValues('suffix', suffix)
        else:
            entry.setValues('backend', bename)
        if maxusn_to_delete:
            entry.setValues('maxusn_to_delete')

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add USN tombstone cleanup task")
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: USN tombstone cleanup task (%s) exited with %d" % (cn, exitCode))
        else:
            self.log.info("USN tombstone cleanup task (%s) completed successfully" % (cn))
        return exitCode
Exemplo n.º 58
0
def test_silent_memberof_failure(topology_st):
    """This test checks that if during a MODRDN, the memberof plugin fails
    then MODRDN also fails

    :id: 095aee01-581c-43dd-a241-71f9631a18bb
    :setup: Standalone Instance
    :steps:
        1. configure memberof to only scope ou=people,SUFFIX
        2. Do some cleanup and Creates 10 users
        3. Create groups0 (IN peoplebase) that contain user0 and user1
        4. Check user0 and user1 have memberof=group0.dn
        5. Create group1 (OUT peoplebase) that contain user0 and user1
        6. Check user0 and user1 have NOT memberof=group1.dn
        7. Move group1 IN peoplebase and check users0 and user1 HAVE memberof=group1.dn
        8. Create group2 (OUT peoplebase) that contain user2 and user3.
        9. Check user2 and user3 have NOT memberof=group2.dn
        10. configure memberof so that added objectclass does not allow 'memberof' attribute
        11. Move group2 IN peoplebase and check move failed OPERATIONS_ERROR (because memberof failed)
        12. Check user2 and user3 have NOT memberof=group2.dn
        13. ADD group3 (IN peoplebase) with user4 and user5 members and check add failed OPERATIONS_ERROR (because memberof failed)
        14. Check user4 and user5 have NOT memberof=group2.dn
    :expectedresults:
        1. should succeed
        2. should succeed
        3. should succeed
        4. should succeed
        5. should succeed
        6. should succeed
        7. should succeed
        8. should succeed
        9. should succeed
        10. should succeed
        11. should fail OPERATION_ERROR because memberof plugin fails to add 'memberof' to members.
        12. should succeed
        13. should fail OPERATION_ERROR because memberof plugin fails to add 'memberof' to members
        14. should succeed
    """
    # only scopes peoplebase
    _config_memberof_silent_memberof_failure(topology_st.standalone)
    topology_st.standalone.restart(timeout=10)

    # first do some cleanup
    peoplebase = 'ou=people,%s' % SUFFIX
    for i in range(10):
        cn = 'user%d' % i
        dn = 'cn=%s,%s' % (cn, peoplebase)
        topology_st.standalone.delete_s(dn)
    topology_st.standalone.delete_s('cn=group_in0,%s' % peoplebase)
    topology_st.standalone.delete_s('cn=group_in1,%s' % peoplebase)
    topology_st.standalone.delete_s('cn=group_out2,%s' % SUFFIX)

    # create 10 users
    for i in range(10):
        cn = 'user%d' % i
        dn = 'cn=%s,%s' % (cn, peoplebase)
        log.fatal('Adding user (%s): ' % dn)
        topology_st.standalone.add_s(
            Entry((dn, {
                'objectclass': ['top', 'person'],
                'sn': 'user_%s' % cn,
                'description': 'add on standalone'
            })))

    # Check that members of group0 (in the scope) have 'memberof
    group0_dn = 'cn=group_in0,%s' % peoplebase
    topology_st.standalone.add_s(
        Entry((group0_dn, {
            'objectclass': ['top', 'groupofnames'],
            'member': [
                'cn=user0,%s' % peoplebase,
                'cn=user1,%s' % peoplebase,
            ],
            'description':
            'mygroup'
        })))

    # Check the those entries have memberof with group0
    for i in range(2):
        user_dn = 'cn=user%d,%s' % (i, peoplebase)
        ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE,
                                              "(objectclass=*)", ['memberof'])
        assert ent.hasAttr('memberof')
        found = False
        for val in ent.getValues('memberof'):
            topology_st.standalone.log.info(
                "!!!!!!! %s: memberof->%s (vs %s)" %
                (user_dn, val, group0_dn.encode().lower()))
            if val.lower() == group0_dn.encode().lower():
                found = True
                break
        assert found

    # Create a group1 out of the scope
    group1_dn = 'cn=group_out1,%s' % SUFFIX
    topology_st.standalone.add_s(
        Entry((group1_dn, {
            'objectclass': ['top', 'groupofnames'],
            'member': [
                'cn=user0,%s' % peoplebase,
                'cn=user1,%s' % peoplebase,
            ],
            'description':
            'mygroup'
        })))

    # Check the those entries have not memberof with group1
    for i in range(2):
        user_dn = 'cn=user%d,%s' % (i, peoplebase)
        ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE,
                                              "(objectclass=*)", ['memberof'])
        assert ent.hasAttr('memberof')
        found = False
        for val in ent.getValues('memberof'):
            topology_st.standalone.log.info(
                "!!!!!!! %s: memberof->%s (vs %s)" %
                (user_dn, val, group1_dn.encode().lower()))
            if val.lower() == group1_dn.encode().lower():
                found = True
                break
        assert not found

    # move group1 into the scope and check user0 and user1 are memberof group1
    topology_st.standalone.rename_s(group1_dn,
                                    'cn=group_in1',
                                    newsuperior=peoplebase,
                                    delold=0)
    new_group1_dn = 'cn=group_in1,%s' % peoplebase
    for i in range(2):
        user_dn = 'cn=user%d,%s' % (i, peoplebase)
        ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE,
                                              "(objectclass=*)", ['memberof'])
        assert ent.hasAttr('memberof')
        found = False
        for val in ent.getValues('memberof'):
            topology_st.standalone.log.info(
                "!!!!!!! %s: memberof->%s (vs %s)" %
                (user_dn, val, new_group1_dn.encode().lower()))
            if val.lower() == new_group1_dn.encode().lower():
                found = True
                break
        assert found

    # Create a group2 out of the scope
    group2_dn = 'cn=group_out2,%s' % SUFFIX
    topology_st.standalone.add_s(
        Entry((group2_dn, {
            'objectclass': ['top', 'groupofnames'],
            'member': [
                'cn=user2,%s' % peoplebase,
                'cn=user3,%s' % peoplebase,
            ],
            'description':
            'mygroup'
        })))

    # Check the those entries have not memberof with group2
    for i in (2, 3):
        user_dn = 'cn=user%d,%s' % (i, peoplebase)
        ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE,
                                              "(objectclass=*)", ['memberof'])
        assert not ent.hasAttr('memberof')

    # memberof will not add the missing objectclass
    _disable_auto_oc_memberof(topology_st.standalone)
    topology_st.standalone.restart(timeout=10)

    # move group2 into the scope and check it fails
    try:
        topology_st.standalone.rename_s(group2_dn,
                                        'cn=group_in2',
                                        newsuperior=peoplebase,
                                        delold=0)
        topology_st.standalone.log.info(
            "This is unexpected, modrdn should fail as the member entry have not the appropriate objectclass"
        )
        assert False
    except ldap.OBJECT_CLASS_VIOLATION:
        pass

    # Check the those entries have not memberof
    for i in (2, 3):
        user_dn = 'cn=user%d,%s' % (i, peoplebase)
        ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE,
                                              "(objectclass=*)", ['memberof'])
        topology_st.standalone.log.info("Should assert %s has memberof is %s" %
                                        (user_dn, ent.hasAttr('memberof')))
        assert not ent.hasAttr('memberof')

    # Create a group3 in the scope
    group3_dn = 'cn=group3_in,%s' % peoplebase
    try:
        topology_st.standalone.add_s(
            Entry((group3_dn, {
                'objectclass': ['top', 'groupofnames'],
                'member': [
                    'cn=user4,%s' % peoplebase,
                    'cn=user5,%s' % peoplebase,
                ],
                'description':
                'mygroup'
            })))
        topology_st.standalone.log.info(
            "This is unexpected, ADD should fail as the member entry have not the appropriate objectclass"
        )
        assert False
    except ldap.OBJECT_CLASS_VIOLATION:
        pass
    except ldap.OPERATIONS_ERROR:
        pass

    # Check the those entries do not have memberof
    for i in (4, 5):
        user_dn = 'cn=user%d,%s' % (i, peoplebase)
        ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE,
                                              "(objectclass=*)", ['memberof'])
        topology_st.standalone.log.info("Should assert %s has memberof is %s" %
                                        (user_dn, ent.hasAttr('memberof')))
        assert not ent.hasAttr('memberof')
Exemplo n.º 59
0
    def upgradeDB(self, nsArchiveDir=None, nsDatabaseType=None, nsForceToReindex=None, args=None):
        '''
        @param nsArchiveDir - The archive directory
        @param nsDatabaseType - The database type - default is "ldbm database"
        @param nsForceToReindex - True/False - force reindexing to occur
        @param args - is a dictionary that contains modifier of the task
                wait: True/[False] - If True,  waits for the completion of the task before to return
        @return exit code
        @raise ValueError: If missing nsArchiveDir
        '''

        if not nsArchiveDir:
            raise ValueError("Missing required paramter: nsArchiveDir")

        cn = 'task-' + time.strftime("%m%d%Y_%H%M%S", time.localtime())
        dn = ('cn=%s,cn=upgradedb,cn=tasks,cn=config' % cn)
        entry = Entry(dn)
        entry.setValues('objectclass', 'top', 'extensibleObject')
        entry.setValues('cn', cn)
        entry.setValues('nsArchiveDir', nsArchiveDir)
        if nsDatabaseType:
            entry.setValues('nsDatabaseType', nsDatabaseType)
        if nsForceToReindex:
            entry.setValues('nsForceToReindex', 'True')

        # start the task and possibly wait for task completion
        try:
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS:
            self.log.error("Fail to add upgradedb task")
            return -1

        exitCode = 0
        if args and args.get(TASK_WAIT, False):
            (done, exitCode) = self.conn.tasks.checkTask(entry, True)

        if exitCode:
            self.log.error("Error: upgradedb task (%s) exited with %d" % (cn, exitCode))
        else:
            self.log.info("Upgradedb task (%s) completed successfully" % (cn))
        return exitCode
Exemplo n.º 60
0
def test_ticket47676_skip_oc_at(topology_m2):
    '''
        This test ADD an entry on SUPPLIER1 where 47676 is fixed. Then it checks that entry is replicated
        on SUPPLIER2 (even if on SUPPLIER2 47676 is NOT fixed). Then update on SUPPLIER2.
        If the schema has successfully been pushed, updating Supplier2 should succeed
    '''
    topology_m2.ms["supplier1"].log.info("\n\n######################### ADD ######################\n")

    # bind as 'cn=Directory manager'
    topology_m2.ms["supplier1"].log.info("Bind as %s and add the add the entry with specific oc" % DN_DM)
    topology_m2.ms["supplier1"].simple_bind_s(DN_DM, PASSWORD)

    # Prepare the entry with multivalued members
    entry = Entry(ENTRY_DN)
    entry.setValues('objectclass', 'top', 'person', 'OCticket47676')
    entry.setValues('sn', ENTRY_NAME)
    entry.setValues('cn', ENTRY_NAME)
    entry.setValues('postalAddress', 'here')
    entry.setValues('postalCode', '1234')
    members = []
    for cpt in range(MAX_OTHERS):
        name = "%s%d" % (OTHER_NAME, cpt)
        members.append("cn=%s,%s" % (name, SUFFIX))
    members.append(BIND_DN)
    entry.setValues('member', members)

    topology_m2.ms["supplier1"].log.info("Try to add Add  %s should be successful" % ENTRY_DN)
    topology_m2.ms["supplier1"].add_s(entry)

    #
    # Now check the entry as been replicated
    #
    topology_m2.ms["supplier2"].simple_bind_s(DN_DM, PASSWORD)
    topology_m2.ms["supplier1"].log.info("Try to retrieve %s from Supplier2" % ENTRY_DN)
    replication_check(topology_m2)
    ent = topology_m2.ms["supplier2"].getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)")
    assert ent
    # Now update the entry on Supplier2 (as DM because 47676 is possibly not fixed on M2)
    topology_m2.ms["supplier1"].log.info("Update  %s on M2" % ENTRY_DN)
    mod = [(ldap.MOD_REPLACE, 'description', b'test_add')]
    topology_m2.ms["supplier2"].modify_s(ENTRY_DN, mod)

    topology_m2.ms["supplier1"].simple_bind_s(DN_DM, PASSWORD)
    replication_check(topology_m2)
    ent = topology_m2.ms["supplier1"].getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)")
    assert ensure_str(ent.getValue('description')) == 'test_add'