コード例 #1
0
def test_filter_validation_enabled(topology_st):
    """Test that queries which are invalid, are correctly rejected by the server.

    :id: 05afdbbd-0d7f-4774-958c-2139827fed70
    :setup: Standalone instance
    :steps:
        1. Search a well formed query
        2. Search a poorly formed query
        3. Search a poorly formed complex (and/or) query
        4. Test the server can be restarted
    :expectedresults:
        1. No warnings
        2. Query is rejected (err)
        3. Query is rejected (err)
        4. Server restarts
    """
    inst = topology_st.standalone

    # In case the default has changed, we set the value to warn.
    inst.config.set("nsslapd-verify-filter-schema", "reject-invalid")
    raw_objects = DSLdapObjects(inst, basedn=DEFAULT_SUFFIX)

    # Check a good query has no errors.
    r = raw_objects.filter("(objectClass=*)")

    with pytest.raises(ldap.UNWILLING_TO_PERFORM):
        # Check a bad one DOES emit an error.
        r = raw_objects.filter("(a=a)")

    with pytest.raises(ldap.UNWILLING_TO_PERFORM):
        # Check a bad complex one does emit an error.
        r = raw_objects.filter("(&(a=a)(b=b)(objectClass=*))")

    # Does restart work?
    inst.restart()
コード例 #2
0
def test_num_subordinates_with_monitor_suffix(topo):
    """This test is to compare the numSubordinates value on the root entry
    with the actual number of direct subordinate(s).

    :id: fdcfe0ac-33c3-4252-bf38-79819ec58a51
    :setup: Single instance
    :steps:
        1. Create sample entries and perform a search with basedn as cn=monitor,
        filter as "(objectclass=*)" and scope as base.
        2. Extract the numSubordinates value.
        3. Perform another search with basedn as cn=monitor, filter as
        "(|(objectclass=*)(objectclass=ldapsubentry))" and scope as one.
        4. Compare numSubordinates value with the number of sub-entries.
    :expectedresults:
        1. Success
        2. Success
        3. Success
        4. Should be same
    """

    raw_objects = DSLdapObjects(topo.standalone, basedn='cn=monitor')
    filter1 = raw_objects.filter("(objectclass=*)", scope=0)
    num_subordinates_val = filter1[0].get_attr_val_int('numSubordinates')
    filter2 = raw_objects.filter(
        "(|(objectclass=*)(objectclass=ldapsubentry))", scope=1)
    assert len(filter2) == num_subordinates_val
コード例 #3
0
def test_produce_division_by_zero(topology_st, create_dummy_mount,
                                  change_config):
    """Test dirsrv will not crash when division by zero occurs

    :id: 51b11093-8851-41bd-86cb-217b1a3339c7
    :customerscenario: True
    :setup: Standalone
    :steps:
        1. Turn on disk monitoring
        2. Go below the threshold
        3. Check DS is up and not entering shutdown mode
    :expectedresults:
        1. Success
        2. Success
        3. Success
    """

    standalone = topology_st.standalone

    log.info(
        'Check search works before changing the nsslapd-auditlog attribute')
    try:
        DSLdapObjects(topology_st.standalone,
                      basedn='cn=disk space,cn=monitor').filter(
                          "(objectclass=*)", scope=0)
    except ldap.SERVER_DOWN as e:
        log.info('Test failed - dirsrv crashed')
        assert False

    log.info('Change location of nsslapd-auditlog')
    standalone.config.set(
        'nsslapd-auditlog',
        '/var/log/dirsrv/slapd-{}/tmp/audit'.format(standalone.serverid))

    log.info('Check search will not fail')
    try:
        DSLdapObjects(topology_st.standalone,
                      basedn='cn=disk space,cn=monitor').filter(
                          "(objectclass=*)", scope=0)
    except ldap.SERVER_DOWN as e:
        log.info('Test failed - dirsrv crashed')
        assert False

    log.info('If passed, run search again just in case')
    try:
        DSLdapObjects(topology_st.standalone,
                      basedn='cn=disk space,cn=monitor').filter(
                          "(objectclass=*)", scope=0)
    except ldap.SERVER_DOWN as e:
        log.info('Test failed - dirsrv crashed')
        assert False
コード例 #4
0
def test_filter_validation_warn_safe(topology_st):
    """Test that queries which are invalid, are correctly marked as "notes=F" in
    the access log, and return no entries or partial sets.

    :id: 8b2b23fe-d878-435c-bc84-8c298be4ca1f
    :setup: Standalone instance
    :steps:
        1. Search a well formed query
        2. Search a poorly formed query
        3. Search a poorly formed complex (and/or) query
    :expectedresults:
        1. No warnings
        2. notes=F is present
        3. notes=F is present
    """
    inst = topology_st.standalone

    # In case the default has changed, we set the value to warn.
    inst.config.set("nsslapd-verify-filter-schema", "process-safe")
    # Set the access log to un-buffered so we get it immediately.
    inst.config.set("nsslapd-accesslog-logbuffering", "off")

    # Setup the query object.
    # Now we don't care if there are any results, we only care about good/bad queries.
    # To do this we have to bypass some of the lib389 magic, and just emit raw queries
    # to check them. Turns out lib389 is well designed and this just works as expected
    # if you use a single DSLdapObjects and filter. :)
    raw_objects = DSLdapObjects(inst, basedn=DEFAULT_SUFFIX)

    # Find any initial notes=F
    access_log = DirsrvAccessLog(inst)
    r_init = access_log.match(".*notes=F.*")

    # Check a good query has no warnings.
    r = raw_objects.filter("(objectClass=*)")
    assert(len(r) > 0)
    r_s1 = access_log.match(".*notes=F.*")
    # Should be the same number of log lines IE 0.
    assert(len(r_init) == len(r_s1))

    # Check a bad one DOES emit a warning.
    r = raw_objects.filter("(a=a)")
    assert(len(r) == 0)
    r_s2 = access_log.match(".*notes=F.*")
    # Should be the greate number of log lines IE +1
    assert(len(r_init) + 1 == len(r_s2))

    # Check a bad complex one does emit a warning.
    r = raw_objects.filter("(&(a=a)(b=b)(objectClass=*))")
    assert(len(r) == 0)
    r_s3 = access_log.match(".*notes=F.*")
    # Should be the greate number of log lines IE +2
    assert(len(r_init) + 2 == len(r_s3))

    # Check that we can still get things when partial
    r = raw_objects.filter("(|(a=a)(b=b)(uid=foo))")
    assert(len(r) == 1)
    r_s4 = access_log.match(".*notes=F.*")
    # Should be the greate number of log lines IE +2
    assert(len(r_init) + 3 == len(r_s4))
コード例 #5
0
def test_indexing_is_online(topo):
    """Test that the changenmumber index is online right after enabling the plugin

    :id: 16f4c001-9e0c-4448-a2b3-08ac1e85d40f
    :setup: Standalone Instance
    :steps:
        1. Enable retro cl
        2. Perform some updates
        3. Search for "(changenumber>=-1)", and it is not partially unindexed
        4. Search for "(&(changenumber>=-1)(targetuniqueid=*))", and it is not partially unindexed
    :expectedresults:
        1. Success
        2. Success
        3. Success
        4. Success
    """

    # Enable plugin
    topo.standalone.config.set('nsslapd-accesslog-logbuffering', 'off')
    plugin = RetroChangelogPlugin(topo.standalone)
    plugin.enable()
    topo.standalone.restart()

    # Do a bunch of updates
    users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
    user_entry = users.create(
        properties={
            'sn': '1',
            'cn': 'user 1',
            'uid': 'user1',
            'uidNumber': '11',
            'gidNumber': '111',
            'givenname': 'user1',
            'homePhone': '0861234567',
            'carLicense': '131D16674',
            'mail': '*****@*****.**',
            'homeDirectory': '/home'
        })
    for count in range(0, 10):
        user_entry.replace('mail', f'test{count}@test.com')

    # Search the retro cl, and check for error messages
    filter_simple = '(changenumber>=-1)'
    filter_compound = '(&(changenumber>=-1)(targetuniqueid=*))'
    retro_changelog_suffix = DSLdapObjects(topo.standalone,
                                           basedn=RETROCL_SUFFIX)
    retro_changelog_suffix.filter(filter_simple)
    assert not topo.standalone.searchAccessLog('Partially Unindexed Filter')

    # Search the retro cl again with compound filter
    retro_changelog_suffix.filter(filter_compound)
    assert not topo.standalone.searchAccessLog('Partially Unindexed Filter')
コード例 #6
0
def test_schema_operation(topo):
    """Test that the cases in original schema are preserved.
       Test that duplicated schema except cases are not loaded
       Test to use a custom schema

    :id: e7448863-ac62-4b49-b013-4efa412c0455
    :setup: Standalone instance
    :steps:
        1. Create a test schema with cases
        2. Run a schema_reload task
        3. Check the attribute is present
        4. Case 2: Check duplicated schema except cases are not loaded
        5. Case 2-1: Use the custom schema

    :expectedresults:
        1. Operation should be successful
        2. Operation should be successful
        3. Operation should be successful
        4. Operation should be successful
        5. Operation should be successful
    """

    log.info('case 1: Test the cases in the original schema are preserved.')

    schema_filename = topo.standalone.schemadir + '/98test.ldif'
    try:
        with open(schema_filename, "w") as schema_file:
            schema_file.write("dn: cn=schema\n")
            schema_file.write(
                "attributetypes: ( 8.9.10.11.12.13.14 NAME " +
                "'MoZiLLaaTTRiBuTe' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 " +
                " X-ORIGIN 'Mozilla Dummy Schema' )\n")
            schema_file.write(
                "objectclasses: ( 1.2.3.4.5.6.7 NAME 'MozillaObject' " +
                "SUP top MUST ( objectclass $ cn ) MAY ( MoZiLLaaTTRiBuTe )" +
                " X-ORIGIN 'user defined' )')\n")

    except OSError as e:
        log.fatal("Failed to create schema file: " +
                  "{} Error: {}".format(schema_filename, str(e)))

    # run the schema reload task with the default schemadir
    schema = Schema(topo.standalone)
    task = schema.reload(schema_dir=topo.standalone.schemadir)
    task.wait()

    subschema = topo.standalone.schema.get_subschema()
    at_obj = subschema.get_obj(ldap.schema.AttributeType, 'MoZiLLaaTTRiBuTe')

    assert at_obj is not None, "The attribute was not found on server"

    log.info('Case 2: Duplicated schema except cases are not loaded.')

    schema_filename = topo.standalone.schemadir + '/97test.ldif'
    try:
        with open(schema_filename, "w") as schema_file:
            Mozattr1 = "MOZILLAATTRIBUTE"
            schema_file.write("dn: cn=schema\n")
            schema_file.write(
                "attributetypes: ( 8.9.10.11.12.13.14 NAME " +
                "'MOZILLAATTRIBUTE' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 " +
                "X-ORIGIN 'Mozilla Dummy Schema' )\n")
            schema_file.write(
                "objectclasses: ( 1.2.3.4.5.6.7 NAME 'MozillaObject' " +
                "SUP top MUST ( objectclass $ cn ) MAY ( MOZILLAATTRIBUTE ) " +
                "X-ORIGIN 'user defined' )')\n")

    except OSError as e:
        log.fatal("Failed to create schema file: " +
                  "{} Error: {}".format(schema_filename, str(e)))

    # run the schema reload task with the default schemadir
    task = schema.reload(schema_dir=topo.standalone.schemadir)
    task.wait()

    subschema_duplicate = topo.standalone.schema.get_subschema()
    at_obj_duplicate = subschema_duplicate.get_obj(ldap.schema.AttributeType,
                                                   'MOZILLAATTRIBUTE')

    moz = re.findall('MOZILLAATTRIBUTE', str(at_obj_duplicate))
    if moz:
        log.error(
            'case 2: MOZILLAATTRIBUTE is in the objectclasses list -- FAILURE')
        assert False
    else:
        log.info(
            'case 2: MOZILLAATTRIBUTE is not in the objectclasses list -- PASS'
        )

    Mozattr2 = "mozillaattribute"
    log.info(f'Case 2-1: Use the custom schema with {Mozattr2}')
    name = "test_user"
    ld = ldap.initialize(topo.standalone.get_ldap_uri())
    ld.simple_bind_s(DN_DM, PW_DM)
    ld.add_s(f"cn={name},{DEFAULT_SUFFIX}",
             [('objectclass', [b'top', b'person', b'MozillaObject']),
              ('sn', [ensure_bytes(name)]), ('cn', [ensure_bytes(name)]),
              (Mozattr2, [ensure_bytes(name)])])

    mozattrval = DSLdapObjects(
        topo.standalone,
        DEFAULT_SUFFIX).filter('(objectclass=mozillaobject)')[0]
    assert mozattrval.get_attr_val_utf8('mozillaattribute') == name
コード例 #7
0
def test_retrocl_exclude_attr_add(topology_st):
    """ Test exclude attribute feature of the retrocl plugin for add operation

    :id: 3481650f-2070-45ef-9600-2500cfc51559

    :setup: Standalone instance

    :steps:
        1. Enable dynamic plugins
        2. Confige retro changelog plugin
        3. Add an entry
        4. Ensure entry attrs are in the changelog
        5. Exclude an attr
        6. Add another entry
        7. Ensure excluded attr is not in the changelog

    :expectedresults:
        1. Success
        2. Success
        3. Success
        4. Success
        5. Success
        6. Success
        7. Success
    """

    st = topology_st.standalone

    log.info('Configure retrocl plugin')
    rcl = RetroChangelogPlugin(st)
    rcl.disable()
    rcl.enable()
    rcl.replace('nsslapd-attribute', 'nsuniqueid:targetUniqueId')

    log.info('Restarting instance')
    try:
        st.restart()
    except ldap.LDAPError as e:
        ldap.error('Failed to restart instance ' + e.args[0]['desc'])
        assert False

    users = UserAccounts(st, DEFAULT_SUFFIX)

    log.info('Adding user1')
    try:
        users.create(
            properties={
                'sn': '1',
                'cn': 'user 1',
                'uid': 'user1',
                'uidNumber': '11',
                'gidNumber': '111',
                'givenname': 'user1',
                'homePhone': '0861234567',
                'carLicense': '131D16674',
                'mail': '*****@*****.**',
                'homeDirectory': '/home/user1',
                'userpassword': USER_PW
            })
    except ldap.ALREADY_EXISTS:
        pass
    except ldap.LDAPError as e:
        log.error("Failed to add user1: " + str(e))

    log.info(
        'Verify homePhone and carLicense attrs are in the changelog changestring'
    )
    try:
        retro_changelog_suffix = DSLdapObjects(st, basedn=RETROCL_SUFFIX)
        cllist = retro_changelog_suffix.filter(f'(targetDn={USER1_DN})')
    except ldap.LDAPError as e:
        log.fatal("Changelog search failed, error: " + str(e))
        assert False
    assert len(cllist) > 0
    if cllist[0].present('changes'):
        clstr = str(cllist[0].get_attr_vals_utf8('changes'))
        assert ATTR_HOMEPHONE in clstr
        assert ATTR_CARLICENSE in clstr

    log.info('Excluding attribute ' + ATTR_HOMEPHONE)
    args = FakeArgs()
    args.connections = [
        st.host + ':' + str(st.port) + ':' + DN_DM + ':' + PW_DM
    ]
    args.instance = 'standalone1'
    args.basedn = None
    args.binddn = None
    args.starttls = False
    args.pwdfile = None
    args.bindpw = None
    args.prompt = False
    args.exclude_attrs = ATTR_HOMEPHONE
    args.func = retrochangelog_add
    dsrc_inst = dsrc_arg_concat(args, None)
    inst = connect_instance(dsrc_inst, False, args)
    result = args.func(inst, None, log, args)
    disconnect_instance(inst)
    assert result is None

    log.info('Restarting instance')
    try:
        st.restart()
    except ldap.LDAPError as e:
        ldap.error('Failed to restart instance ' + e.args[0]['desc'])
        assert False

    log.info('Adding user2')
    try:
        users.create(
            properties={
                'sn': '2',
                'cn': 'user 2',
                'uid': 'user2',
                'uidNumber': '22',
                'gidNumber': '222',
                'givenname': 'user2',
                'homePhone': '0879088363',
                'carLicense': '04WX11038',
                'mail': '*****@*****.**',
                'homeDirectory': '/home/user2',
                'userpassword': USER_PW
            })
    except ldap.ALREADY_EXISTS:
        pass
    except ldap.LDAPError as e:
        log.error("Failed to add user2: " + str(e))

    log.info('Verify homePhone attr is not in the changelog changestring')
    try:
        cllist = retro_changelog_suffix.filter(f'(targetDn={USER2_DN})')
        assert len(cllist) > 0
        if cllist[0].present('changes'):
            clstr = str(cllist[0].get_attr_vals_utf8('changes'))
            assert ATTR_HOMEPHONE not in clstr
            assert ATTR_CARLICENSE in clstr
    except ldap.LDAPError as e:
        log.fatal("Changelog search failed, error: " + str(e))
        assert False
コード例 #8
0
def test_retrocl_exclude_attr_mod(topology_st):
    """ Test exclude attribute feature of the retrocl plugin for mod operation

    :id: f6bef689-685b-4f86-a98d-f7e6b1fcada3

    :setup: Standalone instance

    :steps:
        1. Enable dynamic plugins
        2. Confige retro changelog plugin
        3. Add user1 entry
        4. Ensure entry attrs are in the changelog
        5. Exclude an attr
        6. Modify user1 entry
        7. Ensure excluded attr is not in the changelog

    :expectedresults:
        1. Success
        2. Success
        3. Success
        4. Success
        5. Success
        6. Success
        7. Success
    """

    st = topology_st.standalone

    log.info('Configure retrocl plugin')
    rcl = RetroChangelogPlugin(st)
    rcl.disable()
    rcl.enable()
    rcl.replace('nsslapd-attribute', 'nsuniqueid:targetUniqueId')

    log.info('Restarting instance')
    try:
        st.restart()
    except ldap.LDAPError as e:
        ldap.error('Failed to restart instance ' + e.args[0]['desc'])
        assert False

    users = UserAccounts(st, DEFAULT_SUFFIX)

    log.info('Adding user1')
    try:
        user1 = users.create(
            properties={
                'sn': '1',
                'cn': 'user 1',
                'uid': 'user1',
                'uidNumber': '11',
                'gidNumber': '111',
                'givenname': 'user1',
                'homePhone': '0861234567',
                'carLicense': '131D16674',
                'mail': '*****@*****.**',
                'homeDirectory': '/home/user1',
                'userpassword': USER_PW
            })
    except ldap.ALREADY_EXISTS:
        user1 = UserAccount(st, dn=USER1_DN)
    except ldap.LDAPError as e:
        log.error("Failed to add user1: " + str(e))

    log.info(
        'Verify homePhone and carLicense attrs are in the changelog changestring'
    )
    try:
        retro_changelog_suffix = DSLdapObjects(st, basedn=RETROCL_SUFFIX)
        cllist = retro_changelog_suffix.filter(f'(targetDn={USER1_DN})')
    except ldap.LDAPError as e:
        log.fatal("Changelog search failed, error: " + str(e))
        assert False
    assert len(cllist) > 0
    if cllist[0].present('changes'):
        clstr = str(cllist[0].get_attr_vals_utf8('changes'))
        assert ATTR_HOMEPHONE in clstr
        assert ATTR_CARLICENSE in clstr

    log.info('Excluding attribute ' + ATTR_CARLICENSE)
    args = FakeArgs()
    args.connections = [
        st.host + ':' + str(st.port) + ':' + DN_DM + ':' + PW_DM
    ]
    args.instance = 'standalone1'
    args.basedn = None
    args.binddn = None
    args.starttls = False
    args.pwdfile = None
    args.bindpw = None
    args.prompt = False
    args.exclude_attrs = ATTR_CARLICENSE
    args.func = retrochangelog_add
    dsrc_inst = dsrc_arg_concat(args, None)
    inst = connect_instance(dsrc_inst, False, args)
    result = args.func(inst, None, log, args)
    disconnect_instance(inst)
    assert result is None

    log.info('Restarting instance')
    try:
        st.restart()
    except ldap.LDAPError as e:
        ldap.error('Failed to restart instance ' + e.args[0]['desc'])
        assert False

    log.info('Modify user1 carLicense attribute')
    try:
        user1.replace(ATTR_CARLICENSE, "123WX321")
    except ldap.LDAPError as e:
        log.fatal(
            'test_retrocl_exclude_attr_mod: Failed to update user1 attribute: error '
            + e.message['desc'])
        assert False

    log.info('Verify carLicense attr is not in the changelog changestring')
    try:
        cllist = retro_changelog_suffix.filter(f'(targetDn={USER1_DN})')
        assert len(cllist) > 0
        # There will be 2 entries in the changelog for this user, we are only
        #interested in the second one, the modify operation.
        if cllist[1].present('changes'):
            clstr = str(cllist[1].get_attr_vals_utf8('changes'))
            assert ATTR_CARLICENSE not in clstr
    except ldap.LDAPError as e:
        log.fatal("Changelog search failed, error: " + str(e))
        assert False
コード例 #9
0
def test_tombstone_cleanup(plugin):
    """
    Assert that the USN plugin removes tombstone entries when the cleanup task
    is run. Test removal for a specific backend, a specific suffix, and up to
    a given USN number.
    """
    # create a new backend and a new sub-suffix stored in the new backend
    ou_value = "People3"
    ou_suffix = DEFAULT_SUFFIX
    plugin._instance.backends.create(None,
                                     properties={
                                         BACKEND_NAME:
                                         "People3Data",
                                         BACKEND_SUFFIX:
                                         "ou=" + ou_value + "," + ou_suffix,
                                     })

    ou2 = create_test_ou(plugin._instance, ou=ou_value, suffix=ou_suffix)

    tombstones_b1 = DSLdapObjects(plugin._instance)
    tombstones_b1._basedn = "ou=People," + DEFAULT_SUFFIX
    tombstones_b1._objectclasses = ['nsTombstone']

    tombstones_b2 = DSLdapObjects(plugin._instance)
    tombstones_b2._basedn = ou2.dn
    tombstones_b2._objectclasses = ['nsTombstone']

    root_dse = RootDSE(plugin._instance)
    lastusn_b1 = lambda: root_dse.get_attr_val_int("lastusn;userroot")
    assert lastusn_b1() == -1

    user1_b1 = create_test_user(plugin._instance)
    user2_b1 = create_test_user(plugin._instance)
    user3_b1 = create_test_user(plugin._instance)

    user1_b2 = create_test_user(plugin._instance, suffix=ou2.dn)
    user2_b2 = create_test_user(plugin._instance, suffix=ou2.dn)

    # assert no tombstones exist at this point
    assert not tombstones_b1.list()
    assert not tombstones_b2.list()

    # create 3 tombstone entries on default backend
    user1_b1.delete()
    user2_b1.delete()
    user3_b1.delete()

    # assert there are 3 tombstone entries indeed on default backend
    assert len(tombstones_b1.list()) == 3
    assert not tombstones_b2.list()

    assert lastusn_b1() == 5

    # remove all tombstone entries from default backend, with a USN value up to 4
    task = plugin.cleanup(suffix=DEFAULT_SUFFIX, max_usn=lastusn_b1() - 1)
    task.wait()

    # assert all tombstone entries were deleted but the last one on default backend
    assert len(tombstones_b1.list()) == 1
    assert not tombstones_b2.list()

    # create 2 tombstone entries on new backend
    user1_b2.delete()
    user2_b2.delete()

    # assert there are 2 tombstone entries indeed on new backend
    assert len(tombstones_b2.list()) == 2
    assert len(tombstones_b1.list()) == 1

    # remove all tombstone entries from ou2 suffix
    task = plugin.cleanup(suffix=ou2.dn)
    task.wait()

    # assert there are no tombstone entries stored on ou2 suffix
    assert not tombstones_b2.list()
    assert len(tombstones_b1.list()) == 1

    # reset USN for subsequent test cases
    b = Backend(plugin._instance, dn="cn=people3data," + DN_LDBM)
    reset_USN(plugin, [ou2, b])