Ejemplo n.º 1
0
def _find_memberof(server, member_dn, group_dn):
    #To get the specific server's (M1, C1 and H1) user and group
    user = UserAccount(server, member_dn)
    assert user.exists()
    group = Group(server, group_dn)
    assert group.exists()

    #test that the user entry should have memberof attribute with sepecified group dn value
    assert group._dn in user.get_attr_vals_utf8('memberOf')
Ejemplo n.º 2
0
def test_csnpurge_large_valueset(topo_m2):
    """Test csn generator test

    :id: 63e2bdb2-0a8f-4660-9465-7b80a9f72a74
    :setup: MMR with 2 masters
    :steps:
        1. Create a test_user
        2. add a large set of values (more than 10)
        3. delete all the values (more than 10)
        4. configure the replica to purge those values (purgedelay=5s)
        5. Waiting for 6 second
        6. do a series of update
    :expectedresults:
        1. Should succeeds
        2. Should succeeds
        3. Should succeeds
        4. Should succeeds
        5. Should succeeds
        6. Should not crash
    """
    m1 = topo_m2.ms["master2"]

    test_user = UserAccount(m1, TEST_ENTRY_DN)
    if test_user.exists():
        log.info('Deleting entry {}'.format(TEST_ENTRY_DN))
        test_user.delete()
    test_user.create(
        properties={
            'uid': TEST_ENTRY_NAME,
            'cn': TEST_ENTRY_NAME,
            'sn': TEST_ENTRY_NAME,
            'userPassword': TEST_ENTRY_NAME,
            'uidNumber': '1000',
            'gidNumber': '2000',
            'homeDirectory': '/home/mmrepl_test',
        })

    # create a large value set so that it is sorted
    for i in range(1, 20):
        test_user.add('description', 'value {}'.format(str(i)))

    # delete all values of the valueset
    for i in range(1, 20):
        test_user.remove('description', 'value {}'.format(str(i)))

    # set purging delay to 5 second and wait more that 5second
    replicas = Replicas(m1)
    replica = replicas.list()[0]
    log.info('nsds5ReplicaPurgeDelay to 5')
    replica.set('nsds5ReplicaPurgeDelay', '5')
    time.sleep(6)

    # add some new values to the valueset containing entries that should be purged
    for i in range(21, 25):
        test_user.add('description', 'value {}'.format(str(i)))
Ejemplo n.º 3
0
def create_entry(topo_m4, request):
    """Add test entry to master1"""

    log.info('Adding entry {}'.format(TEST_ENTRY_DN))

    test_user = UserAccount(topo_m4.ms["master1"], TEST_ENTRY_DN)
    if test_user.exists():
        log.info('Deleting entry {}'.format(TEST_ENTRY_DN))
        test_user.delete()
    test_user.create(
        properties={
            'uid': TEST_ENTRY_NAME,
            'cn': TEST_ENTRY_NAME,
            'sn': TEST_ENTRY_NAME,
            'userPassword': TEST_ENTRY_NAME,
            'uidNumber': '1000',
            'gidNumber': '2000',
            'homeDirectory': '/home/mmrepl_test',
        })
Ejemplo n.º 4
0
def test_urp_trigger_substring_search(topo_m2):
    """Test that a ADD of a entry with a '*' in its DN, triggers
    an internal search with a escaped DN

    :id: 9869bb39-419f-42c3-a44b-c93eb0b77667
    :setup: MMR with 2 masters
    :steps:
        1. enable internal operation loggging for plugins
        2. Create on M1 a test_user with a '*' in its DN
        3. Check the test_user is replicated
        4. Check in access logs that the internal search does not contain '*'
    :expectedresults:
        1. Should succeeds
        2. Should succeeds
        3. Should succeeds
        4. Should succeeds
    """
    m1 = topo_m2.ms["master1"]
    m2 = topo_m2.ms["master2"]

    # Enable loggging of internal operation logging to capture URP intop
    log.info('Set nsslapd-plugin-logging to on')
    for inst in (m1, m2):
        inst.config.loglevel([AccessLog.DEFAULT, AccessLog.INTERNAL],
                             service='access')
        inst.config.set('nsslapd-plugin-logging', 'on')
        inst.restart()

    # add a user with a DN containing '*'
    test_asterisk_uid = 'asterisk_*_in_value'
    test_asterisk_dn = 'uid={},{}'.format(test_asterisk_uid, DEFAULT_SUFFIX)

    test_user = UserAccount(m1, test_asterisk_dn)
    if test_user.exists():
        log.info('Deleting entry {}'.format(test_asterisk_dn))
        test_user.delete()
    test_user.create(
        properties={
            'uid': test_asterisk_uid,
            'cn': test_asterisk_uid,
            'sn': test_asterisk_uid,
            'userPassword': test_asterisk_uid,
            'uidNumber': '1000',
            'gidNumber': '2000',
            'homeDirectory': '/home/asterisk',
        })

    # check that the ADD was replicated on M2
    test_user_m2 = UserAccount(m2, test_asterisk_dn)
    for i in range(1, 5):
        if test_user_m2.exists():
            break
        else:
            log.info('Entry not yet replicated on M2, wait a bit')
            time.sleep(2)

    # check that M2 access logs does not "(&(objectclass=nstombstone)(nscpentrydn=uid=asterisk_*_in_value,dc=example,dc=com))"
    log.info('Check that on M2, URP as not triggered such internal search')
    pattern = ".*\(Internal\).*SRCH.*\(&\(objectclass=nstombstone\)\(nscpentrydn=uid=asterisk_\*_in_value,dc=example,dc=com.*"
    found = m2.ds_access_log.match(pattern)
    log.info("found line: %s" % found)
    assert not found
Ejemplo n.º 5
0
    def test_conflict_attribute_single_valued(self, topology_m2, base_m2):
        """A RDN attribute being signle-valued, checks that after several operations
           MODRDN and MOD_REPL its RDN values are the same on both servers

        :id: c38ae613-5d1e-47cf-b051-c7284e64b817
        :setup: Two master replication, test container for entries, enable plugin logging,
                audit log, error log for replica and access log for internal
        :steps:
            1. Create a test entry uid=user_test_1000,...
            2. Pause all replication agreements
            3. On M1 rename it into employeenumber=foo1,...
            4. On M2 rename it into employeenumber=foo2,...
            5. On M1 MOD_REPL employeenumber:foo1
            6. Resume all replication agreements
            7. Check that entry on M1 has employeenumber=foo1
            8. Check that entry on M2 has employeenumber=foo1
            9. Check that entry on M1 and M2 has the same employeenumber values
        :expectedresults:
            1. It should pass
            2. It should pass
            3. It should pass
            4. It should pass
            5. It should pass
            6. It should pass
            7. It should pass
            8. It should pass
            9. It should pass
        """

        M1 = topology_m2.ms["master1"]
        M2 = topology_m2.ms["master2"]

        # add a test user with a dummy 'uid' extra value because modrdn removes
        # uid that conflict with 'account' objectclass
        test_users_m1 = UserAccounts(M1, base_m2.dn, rdn=None)
        user_1 = test_users_m1.create_test_user(uid=1000)
        user_1.add('objectclass', 'extensibleobject')
        user_1.add('uid', 'dummy')
        test_users_m2 = UserAccount(M2, user_1.dn)

        # Waiting fo the user to be replicated
        for i in range(0, 4):
            time.sleep(1)
            if test_users_m2.exists():
                break
        assert (test_users_m2.exists())

        # Stop replication agreements
        topology_m2.pause_all_replicas()

        # On M1 rename test entry in employeenumber=foo1
        original_dn = user_1.dn
        user_1.rename('employeenumber=foo1')
        time.sleep(1)

        # On M2 rename test entry in employeenumber=foo2
        M2.rename_s(original_dn, 'employeenumber=foo2')
        time.sleep(2)

        # on M1 MOD_REPL uid into foo1
        user_1.replace('employeenumber', 'foo1')

        # resume replication agreements
        topology_m2.resume_all_replicas()
        time.sleep(5)

        # check that on M1, the entry 'employeenumber' has value 'foo1'
        final_dn = re.sub('^.*1000,', 'employeenumber=foo2,', original_dn)
        final_user_m1 = UserAccount(M1, final_dn)
        for val in final_user_m1.get_attr_vals_utf8('employeenumber'):
            log.info("Check %s is on M1" % val)
            assert (val in ['foo1'])

        # check that on M2, the entry 'employeenumber' has values 'foo1'
        final_user_m2 = UserAccount(M2, final_dn)
        for val in final_user_m2.get_attr_vals_utf8('employeenumber'):
            log.info("Check %s is on M2" % val)
            assert (val in ['foo1'])

        # check that the entry have the same uid values
        for val in final_user_m1.get_attr_vals_utf8('employeenumber'):
            log.info("Check M1.uid %s is also on M2" % val)
            assert (val in final_user_m2.get_attr_vals_utf8('employeenumber'))

        for val in final_user_m2.get_attr_vals_utf8('employeenumber'):
            log.info("Check M2.uid %s is also on M1" % val)
            assert (val in final_user_m1.get_attr_vals_utf8('employeenumber'))
Ejemplo n.º 6
0
    def test_conflict_attribute_multi_valued(self, topology_m2, base_m2):
        """A RDN attribute being multi-valued, checks that after several operations
           MODRDN and MOD_REPL its RDN values are the same on both servers

        :id: 225b3522-8ed7-4256-96f9-5fab9b7044a5
        :setup: Two master replication,
                audit log, error log for replica and access log for internal
        :steps:
            1. Create a test entry uid=user_test_1000,...
            2. Pause all replication agreements
            3. On M1 rename it into uid=foo1,...
            4. On M2 rename it into uid=foo2,...
            5. On M1 MOD_REPL uid:foo1
            6. Resume all replication agreements
            7. Check that entry on M1 has uid=foo1, foo2
            8. Check that entry on M2 has uid=foo1, foo2
            9. Check that entry on M1 and M2 has the same uid values
        :expectedresults:
            1. It should pass
            2. It should pass
            3. It should pass
            4. It should pass
            5. It should pass
            6. It should pass
            7. It should pass
            8. It should pass
            9. It should pass
        """

        M1 = topology_m2.ms["master1"]
        M2 = topology_m2.ms["master2"]

        # add a test user
        test_users_m1 = UserAccounts(M1, base_m2.dn, rdn=None)
        user_1 = test_users_m1.create_test_user(uid=1000)
        test_users_m2 = UserAccount(M2, user_1.dn)
        # Waiting fo the user to be replicated
        for i in range(0, 4):
            time.sleep(1)
            if test_users_m2.exists():
                break
        assert (test_users_m2.exists())

        # Stop replication agreements
        topology_m2.pause_all_replicas()

        # On M1 rename test entry in uid=foo1
        original_dn = user_1.dn
        user_1.rename('uid=foo1')
        time.sleep(1)

        # On M2 rename test entry in uid=foo2
        M2.rename_s(original_dn, 'uid=foo2')
        time.sleep(2)

        # on M1 MOD_REPL uid into foo1
        user_1.replace('uid', 'foo1')

        # resume replication agreements
        topology_m2.resume_all_replicas()
        time.sleep(5)

        # check that on M1, the entry 'uid' has two values 'foo1' and 'foo2'
        final_dn = re.sub('^.*1000,', 'uid=foo2,', original_dn)
        final_user_m1 = UserAccount(M1, final_dn)
        for val in final_user_m1.get_attr_vals_utf8('uid'):
            log.info("Check %s is on M1" % val)
            assert (val in ['foo1', 'foo2'])

        # check that on M2, the entry 'uid' has two values 'foo1' and 'foo2'
        final_user_m2 = UserAccount(M2, final_dn)
        for val in final_user_m2.get_attr_vals_utf8('uid'):
            log.info("Check %s is on M1" % val)
            assert (val in ['foo1', 'foo2'])

        # check that the entry have the same uid values
        for val in final_user_m1.get_attr_vals_utf8('uid'):
            log.info("Check M1.uid %s is also on M2" % val)
            assert (val in final_user_m2.get_attr_vals_utf8('uid'))

        for val in final_user_m2.get_attr_vals_utf8('uid'):
            log.info("Check M2.uid %s is also on M1" % val)
            assert (val in final_user_m1.get_attr_vals_utf8('uid'))
Ejemplo n.º 7
0
def test_gecos_directoryString_wins_M2(topo_m2, request):
    """Check that if inital syntax are IA5(M2) and DirectoryString(M1)
    Then directoryString wins when nsSchemaCSN M2 is the greatest

    :id: 2da7f1b1-f86d-4072-a940-ba56d4bc8348
    :setup: Two suppliers replication setup
    :steps:
        1. Create a testuser on M1
        2  Stop M1 and M2
        3  Change gecos def on M2 to be IA5
        4  Start M1 and M2
        5  Update M2 schema so that M2 has greatest nsSchemaCSN
        6  Update testuser on M2 and trigger replication to M1
        7  Update testuser on M2 with gecos directoryString value
        8  Check replication is still working
        9  Check gecos is DirectoryString on M1 and M2
    :expectedresults:
        1. success
        2. success
        3. success
        4. success
        5. success
        6. success
        7. success
        8. success
        9. success

    """

    repl = ReplicationManager(DEFAULT_SUFFIX)
    m1 = topo_m2.ms["supplier1"]
    m2 = topo_m2.ms["supplier2"]

    # create a test user
    testuser_dn = 'uid={},{}'.format('testuser', DEFAULT_SUFFIX)
    testuser = UserAccount(m1, testuser_dn)
    try:
        testuser.create(
            properties={
                'uid': 'testuser',
                'cn': 'testuser',
                'sn': 'testuser',
                'uidNumber': '1000',
                'gidNumber': '2000',
                'homeDirectory': '/home/testuser',
            })
    except ldap.ALREADY_EXISTS:
        pass
    testuser.replace('displayName', 'to trigger replication M1-> M2')
    repl.wait_for_replication(m1, m2)

    # Stop suppliers to update the schema
    m1.stop()
    m2.stop()

    # on M1: gecos is DirectoryString (default)
    # on M2: gecos is IA5
    schema_filename = (m2.schemadir + "/99user.ldif")
    try:
        with open(schema_filename, 'w') as schema_file:
            schema_file.write("dn: cn=schema\n")
            schema_file.write(
                "attributetypes: ( 1.3.6.1.1.1.1.2 NAME " +
                "'gecos' DESC 'The GECOS field; the common name' " +
                "EQUALITY caseIgnoreIA5Match " +
                "SUBSTR caseIgnoreIA5SubstringsMatch " +
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 " + "SINGLE-VALUE )\n")
        os.chmod(schema_filename, 0o777)
    except OSError as e:
        log.fatal("Failed to update schema file: " +
                  "{} Error: {}".format(schema_filename, str(e)))

    # start the instances
    m1.start()
    m2.start()

    # Check that gecos is IA5 on M2
    schema = SchemaLegacy(m2)
    attributetypes = schema.query_attributetype('gecos')
    assert attributetypes[0].syntax == "1.3.6.1.4.1.1466.115.121.1.26"

    # update M2 schema to increase its nsschemaCSN
    new_at = "( dummy-oid NAME 'dummy' DESC 'dummy attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'RFC 2307' )"
    m2.schema.add_schema('attributetypes', ensure_bytes(new_at))

    # update just to trigger replication M2->M1
    # and update of M2 schema
    testuser_m2 = UserAccount(m2, testuser_dn)
    testuser_m2.replace('displayName', 'to trigger replication M2-> M1')

    # Add a gecos UTF value on M1
    testuser.replace('gecos', 'Hélène')

    # Check replication is still working
    testuser.replace('displayName', 'ascii value')
    repl.wait_for_replication(m1, m2)
    assert testuser_m2.exists()
    assert testuser_m2.get_attr_val_utf8('displayName') == 'ascii value'

    # Check that gecos is DirectoryString on M1
    schema = SchemaLegacy(m1)
    attributetypes = schema.query_attributetype('gecos')
    assert attributetypes[0].syntax == "1.3.6.1.4.1.1466.115.121.1.15"

    # Check that gecos is DirectoryString on M2
    schema = SchemaLegacy(m2)
    attributetypes = schema.query_attributetype('gecos')
    assert attributetypes[0].syntax == "1.3.6.1.4.1.1466.115.121.1.15"

    def fin():
        m1.start()
        m2.start()
        testuser.delete()
        m1.schema.del_schema('attributetypes', ensure_bytes(new_at))
        repl.wait_for_replication(m1, m2)

        # on M2 restore a default 99user.ldif
        m2.stop()
        os.remove(m2.schemadir + "/99user.ldif")
        schema_filename = (m2.schemadir + "/99user.ldif")
        try:
            with open(schema_filename, 'w') as schema_file:
                schema_file.write("dn: cn=schema\n")
            os.chmod(schema_filename, 0o777)
        except OSError as e:
            log.fatal("Failed to update schema file: " +
                      "{} Error: {}".format(schema_filename, str(e)))
        m2.start()

    request.addfinalizer(fin)
Ejemplo n.º 8
0
def test_gecos_mixed_definition_topo(topo_m2, request):
    """Check that replication is still working if schema contains
       definitions that does not conform with a replicated entry

    :id: d5940e71-d18a-4b71-aaf7-b9185361fffe
    :setup: Two suppliers replication setup
    :steps:
        1. Create a testuser on M1
        2  Stop M1 and M2
        3  Change gecos def on M2 to be IA5
        4  Update testuser with gecos directoryString value
        5  Check replication is still working
    :expectedresults:
        1. success
        2. success
        3. success
        4. success
        5. success

    """

    repl = ReplicationManager(DEFAULT_SUFFIX)
    m1 = topo_m2.ms["supplier1"]
    m2 = topo_m2.ms["supplier2"]

    # create a test user
    testuser_dn = 'uid={},{}'.format('testuser', DEFAULT_SUFFIX)
    testuser = UserAccount(m1, testuser_dn)
    try:
        testuser.create(
            properties={
                'uid': 'testuser',
                'cn': 'testuser',
                'sn': 'testuser',
                'uidNumber': '1000',
                'gidNumber': '2000',
                'homeDirectory': '/home/testuser',
            })
    except ldap.ALREADY_EXISTS:
        pass
    repl.wait_for_replication(m1, m2)

    # Stop suppliers to update the schema
    m1.stop()
    m2.stop()

    # on M1: gecos is DirectoryString (default)
    # on M2: gecos is IA5
    schema_filename = (m2.schemadir + "/99user.ldif")
    try:
        with open(schema_filename, 'w') as schema_file:
            schema_file.write("dn: cn=schema\n")
            schema_file.write(
                "attributetypes: ( 1.3.6.1.1.1.1.2 NAME " +
                "'gecos' DESC 'The GECOS field; the common name' " +
                "EQUALITY caseIgnoreIA5Match " +
                "SUBSTR caseIgnoreIA5SubstringsMatch " +
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 " + "SINGLE-VALUE )\n")
        os.chmod(schema_filename, 0o777)
    except OSError as e:
        log.fatal("Failed to update schema file: " +
                  "{} Error: {}".format(schema_filename, str(e)))

    # start the instances
    m1.start()
    m2.start()

    # Check that gecos is IA5 on M2
    schema = SchemaLegacy(m2)
    attributetypes = schema.query_attributetype('gecos')
    assert attributetypes[0].syntax == "1.3.6.1.4.1.1466.115.121.1.26"

    # Add a gecos UTF value on M1
    testuser.replace('gecos', 'Hélène')

    # Check replication is still working
    testuser.replace('displayName', 'ascii value')
    repl.wait_for_replication(m1, m2)
    testuser_m2 = UserAccount(m2, testuser_dn)
    assert testuser_m2.exists()
    assert testuser_m2.get_attr_val_utf8('displayName') == 'ascii value'

    def fin():
        m1.start()
        m2.start()
        testuser.delete()
        repl.wait_for_replication(m1, m2)

        # on M2 restore a default 99user.ldif
        m2.stop()
        os.remove(m2.schemadir + "/99user.ldif")
        schema_filename = (m2.schemadir + "/99user.ldif")
        try:
            with open(schema_filename, 'w') as schema_file:
                schema_file.write("dn: cn=schema\n")
            os.chmod(schema_filename, 0o777)
        except OSError as e:
            log.fatal("Failed to update schema file: " +
                      "{} Error: {}".format(schema_filename, str(e)))
        m2.start()
        m1.start()

    request.addfinalizer(fin)
Ejemplo n.º 9
0
def test_replica_backup_and_restore(topo_m4):
    """Test Backup and restore

    :id: 5ad1b85c-e765-11e8-9668-8c16451d917b
    :setup: standalone
    :steps:
        1. Add entries
        2. Take backup db2ldif on supplier1
        3. Delete entries on supplier1
        4. Restore entries ldif2db
        5. Check entries
    :expected results:
        1. Should success
        2. Should success
        3. Should success
        4. Should success
        5. Should success
    """
    # Testing bug #830335: Taking a replica backup and Restore on M1 after deleting few entries from M1 nad M2
    # Make sure to update S1 to avoid useless replication delay
    repl = ReplicationManager(DEFAULT_SUFFIX)
    users = UserAccounts(topo_m4.ms["supplier1"], DEFAULT_SUFFIX)
    for i in range(20, 25):
        users.create_test_user(uid=i)
        time.sleep(1)
    repl.wait_for_replication(topo_m4.ms["supplier1"], topo_m4.ms["supplier2"])
    repl.test_replication(topo_m4.ms["supplier1"], topo_m4.ms["supplier2"], 30)

    # Get a backup
    topo_m4.ms["supplier1"].stop()
    topo_m4.ms["supplier1"].db2ldif(
        bename=DEFAULT_BENAME,
        suffixes=[DEFAULT_SUFFIX],
        excludeSuffixes=[],
        encrypt=False,
        repl_data=True,
        outputfile="/tmp/output_file",
    )

    # Do some updates (that are not in the backup
    # and restore the backup
    topo_m4.ms["supplier1"].start()
    for i in users.list():
        topo_m4.ms["supplier1"].delete_s(i.dn)
    repl.wait_for_replication(topo_m4.ms["supplier1"], topo_m4.ms["supplier2"])
    repl.test_replication(topo_m4.ms["supplier1"], topo_m4.ms["supplier2"], 30)
    # disable the agmt (while server is up) to avoid the DEL get replayed too early
    for agmt in list_agmt_towards(topo_m4, "supplier1"):
        agmt.pause()
    topo_m4.ms["supplier1"].stop()
    topo_m4.ms["supplier1"].ldif2db(
        bename=None,
        excludeSuffixes=None,
        encrypt=False,
        suffixes=[DEFAULT_SUFFIX],
        import_file="/tmp/output_file",
    )
    topo_m4.ms["supplier1"].start()

    # Check that the updates (DEL) are no longer there
    for i in users.list():
        testuser = UserAccount(topo_m4.ms["supplier1"], i.dn)
        assert testuser.exists()

    # Re enable the agmts
    for agmt in list_agmt_towards(topo_m4, "supplier1"):
        agmt.resume()

    # Here the changelog of supplier1 has been cleared.
    # Let's wait the supplier2 resync supplier1 BEFORE doing
    # any update to supplier1.
    # Else (a new update on S1), the others supplier will not update
    # it and the changelog of S1 will not contain the starting points
    # of the others suppliers.
    repl.wait_for_replication(topo_m4.ms["supplier2"], topo_m4.ms["supplier1"])
    repl.wait_for_replication(topo_m4.ms["supplier3"], topo_m4.ms["supplier1"])
    repl.wait_for_replication(topo_m4.ms["supplier4"], topo_m4.ms["supplier1"])

    for i in range(31, 35):
        users.create_test_user(uid=i)
        time.sleep(1)
    repl.wait_for_replication(topo_m4.ms["supplier1"], topo_m4.ms["supplier2"])
    repl.test_replication(topo_m4.ms["supplier1"], topo_m4.ms["supplier2"], 30)