Esempio n. 1
0
def test_mods_replace(topology_st, _create_index_entry, mode):
    """Test mods replace

    :id: 2dd46b7a-b928-11e9-91dd-8c16451d917b
    :parametrized: yes
    :setup: Standalone
    :steps:
        1. Create entry with an attribute that uses matching mode
        2. Add an attribute that uses that matching mode providing duplicate
           values that are duplicates according to the equality matching.
        3. Delete existing entry
    :expected results:
        1. Pass
        2. Fail(ldap.TYPE_OR_VALUE_EXISTS)
        3. Pass
    """
    cos = CosTemplates(topology_st.standalone, DEFAULT_SUFFIX)
    # Entry with extensibleObject
    entry = cos.create(properties={
        'cn': 'addentry' + mode['attr'],
        mode['attr']: mode['positive']
    })
    with pytest.raises(ldap.TYPE_OR_VALUE_EXISTS):
        entry.replace(mode['attr'], mode['negative'])
    entry.delete()
Esempio n. 2
0
def test_valid_invalid_mode_replace(topology_st, mode):
    """Replace and Delete duplicate attribute

    :id: 7ec19eca-8cfc-11e9-a0df-8c16451d917b
    :parametrized: yes
    :setup: Standalone
    :steps:
        1. Create entry with an attribute that uses that matching rule
        2. Replace an attribute that uses that matching rule
        3. Replace an attribute that uses that matching rule providing duplicate
           values that are duplicates according to the equality matching mode.
        4. Delete existing attribute
        5. Try to delete the deleted attribute again.
        6. Delete entry
    :expected results:
        1. Pass
        2. Pass
        3. Fail(ldap.TYPE_OR_VALUE_EXISTS)
        4. Pass
        5. Fail(ldap.NO_SUCH_ATTRIBUTE)
        6. Pass
    """
    # Entry with extensibleObject
    cos = CosTemplates(topology_st.standalone, DEFAULT_SUFFIX)
    user = cos.create(properties={'cn': 'addentry' + mode['attr']})

    # Replace Operation
    user.replace(mode['attr'], mode['positive'])
    with pytest.raises(ldap.TYPE_OR_VALUE_EXISTS):
        user.replace(mode['attr'], mode['negative'])
    # Delete Operation
    user.remove(mode['attr'], mode['positive'][0])
    with pytest.raises(ldap.NO_SUCH_ATTRIBUTE):
        user.remove(mode['attr'], mode['positive'][0])
    user.delete()
Esempio n. 3
0
def test_valid_invalid_attributes(topology_st, _create_index_entry, index):
    """Test valid and invalid values of attributes

    :id: 93dc9e02-b87d-11e9-b39b-8c16451d917b
    :parametrized: yes
    :setup: Standalone
    :steps:
        1. Create entry with an attribute that uses that matching rule
        2. Delete existing entry
        3. Create entry with an attribute that uses that matching rule providing duplicate
           values that are duplicates according to the equality matching rule.
    :expected results:
        1. Pass
        2. Pass
        3. Fail(ldap.TYPE_OR_VALUE_EXISTS)
    """
    cos = CosTemplates(topology_st.standalone, DEFAULT_SUFFIX)
    # Entry with extensibleObject
    entry = cos.create(properties={
        'cn': 'addentry' + index['attr'],
        index['attr']: index['positive']
    })
    entry.delete()
    with pytest.raises(ldap.TYPE_OR_VALUE_EXISTS):
        cos.create(
            properties={
                'cn': 'addentry' + index['attr'].split('attr')[1],
                index['attr']: index['negative']
            })
Esempio n. 4
0
def test_mods_delete(topology_st, _create_index_entry, mode):
    """Test mods delete

    :id: 1dda055e-b928-11e9-b5c1-8c16451d917b
    :parametrized: yes
    :setup: Standalone
    :steps:
        1. Create entry with an attribute that uses matching mode
        2. Add an attribute that uses that matching mode providing duplicate
           values that are duplicates according to the equality matching.
        3. Delete existing entry
    :expected results:
        1. Pass
        2. Fail(ldap.NO_SUCH_ATTRIBUTE)
        3. Pass
    """
    cos = CosTemplates(topology_st.standalone, DEFAULT_SUFFIX)
    # Entry with extensibleObject
    entry = cos.create(properties={
        'cn': 'addentry' + mode['attr'],
        mode['attr']: mode['positive_negative']
    })
    entry.remove(mode['attr'], mode['positive_negative'][0])
    with pytest.raises(ldap.NO_SUCH_ATTRIBUTE):
        entry.remove(mode['attr'], mode['positive_negative'][0])
    entry.delete()
Esempio n. 5
0
def test_valid_invalid_modes(topology_st, mode):
    """Add duplicate attributes

    :id: dec03362-ba26-41da-b479-e2b788403fce
    :parametrized: yes
    :setup: Standalone
    :steps:
        1. Create entry with an attribute that uses matching mode
        2. Add an attribute that uses that matching mode providing duplicate
           values that are duplicates according to the equality matching.
        3. Delete existing entry
    :expected results:
        1. Pass
        2. Fail(ldap.TYPE_OR_VALUE_EXISTS)
        3. Pass
    """
    # Entry with extensibleObject
    cos = CosTemplates(topology_st.standalone, DEFAULT_SUFFIX)
    entry = cos.create(properties={
        'cn': 'addentry' + mode['attr'],
        mode['attr']: mode['positive']
    })
    with pytest.raises(ldap.TYPE_OR_VALUE_EXISTS):
        entry.add(mode['attr'], mode['negative'])
    entry.delete()
Esempio n. 6
0
def test_valid_invalid_attributes(topology_st, rule):
    """Delete duplicate attributes

    :id: d0bf3942-ba71-4947-90c8-1bfa9f0b838f
    :parametrized: yes
    :setup: Standalone
    :steps:
        1. Create entry with an attribute that uses that matching rule
        2. Delete existing entry
        3. Create entry with an attribute that uses that matching rule providing duplicate
           values that are duplicates according to the equality matching rule.
    :expected results:
        1. Pass
        2. Pass
        3. Fail(ldap.TYPE_OR_VALUE_EXISTS)
    """
    # Entry with extensibleObject
    cos = CosTemplates(topology_st.standalone, DEFAULT_SUFFIX)
    entry = cos.create(properties={
        'cn': 'addentry' + rule['attr'],
        rule['attr']: rule['positive']
    })
    entry.delete()
    with pytest.raises(ldap.TYPE_OR_VALUE_EXISTS):
        cos.create(
            properties={
                'cn': 'addentry' + rule['attr'].split('attr')[1],
                rule['attr']: rule['negative']
            })
Esempio n. 7
0
def test_healthcheck_virtual_attr_incorrectly_indexed(topology_st):
    """Check if HealthCheck returns DSVIRTLE0001 code

    :id: 1055173b-21aa-4aaa-9e91-4dc6c5e0c01f
    :setup: Standalone instance
    :steps:
        1. Create DS instance
        2. Create a CoS definition entry
        3. Create the matching CoS template entry, with postalcode as virtual attribute
        4. Create an index for postalcode
        5. Use HealthCheck without --json option
        6. Use HealthCheck with --json option
    :expectedresults:
        1. Success
        2. Success
        3. Success
        4. Success
        5. Healthcheck reports DSVIRTLE0001 code and related details
        6. Healthcheck reports DSVIRTLE0001 code and related details
    """

    RET_CODE = 'DSVIRTLE0001'

    standalone = topology_st.standalone
    postal_index_properties = {
        'cn': 'postalcode',
        'nsSystemIndex': 'False',
        'nsIndexType': ['eq', 'sub', 'pres'],
    }

    log.info(
        'Add cosPointer, cosTemplate and test entry to default suffix, where virtual attribute is postal code'
    )
    cos_pointer_properties = {
        'cn': 'cosPointer',
        'description': 'cosPointer example',
        'cosTemplateDn': 'cn=cosTemplateExample,ou=People,dc=example,dc=com',
        'cosAttribute': 'postalcode',
    }
    cos_pointer_definitions = CosPointerDefinitions(standalone, DEFAULT_SUFFIX,
                                                    'ou=People')
    cos_pointer_definitions.create(properties=cos_pointer_properties)

    log.info('Create CoS template')
    cos_template_properties = {'cn': 'cosTemplateExample', 'postalcode': '117'}
    cos_templates = CosTemplates(standalone, DEFAULT_SUFFIX, 'ou=People')
    cos_templates.create(properties=cos_template_properties)

    log.info('Create an index for postalcode')
    backends = Backends(topology_st.standalone)
    ur_indexes = backends.get('userRoot').get_indexes()
    ur_indexes.create(properties=postal_index_properties)

    run_healthcheck_and_flush_log(topology_st,
                                  standalone,
                                  RET_CODE,
                                  json=False)
    run_healthcheck_and_flush_log(topology_st, standalone, RET_CODE, json=True)
Esempio n. 8
0
def test_usandsconf_dbgen_cos_template(topology_st, set_log_file_and_ldif):
    """Test ldifgen (formerly dbgen) tool to create a COS template

        :id: 544017c7-4a82-4e7d-a047-00b68a28e071
        :setup: Standalone instance
        :steps:
             1. Create DS instance
             2. Run ldifgen to generate ldif with COS template
             3. Import generated ldif to database
             4. Check it was properly imported
        :expectedresults:
             1. Success
             2. Success
             3. Success
             4. Success
        """

    LDAP_RESULT = 'adding new entry "cn=My_Template,ou=cos templates,dc=example,dc=com"'

    standalone = topology_st.standalone

    args = FakeArgs()
    args.NAME = 'My_Template'
    args.parent = 'ou=cos templates,dc=example,dc=com'
    args.create_parent = True
    args.cos_priority = "1"
    args.cos_attr_val = 'postalcode:12345'
    args.ldif_file = ldif_file

    content_list = [
        'Generating LDIF with the following options:',
        'NAME={}'.format(args.NAME), 'parent={}'.format(args.parent),
        'create-parent={}'.format(args.create_parent),
        'cos-priority={}'.format(args.cos_priority),
        'cos-attr-val={}'.format(args.cos_attr_val),
        'ldif-file={}'.format(args.ldif_file), 'Writing LDIF',
        'Successfully created LDIF file: {}'.format(args.ldif_file)
    ]

    log.info('Run ldifgen to create COS template ldif')
    dbgen_create_cos_tmp(standalone, log, args)

    log.info('Check if file exists')
    assert os.path.exists(ldif_file)

    check_value_in_log_and_reset(content_list)

    # Groups, COS, Roles and modification ldifs are designed to be used by ldapmodify, not ldif2db
    run_ldapmodify_from_file(standalone, ldif_file, LDAP_RESULT)

    log.info('Check that COS template is imported')
    cos_temp = CosTemplates(standalone, args.parent)
    assert cos_temp.exists(args.NAME)
    new_cos = cos_temp.get(args.NAME)
    assert new_cos.present('cosPriority', str(args.cos_priority))
    assert new_cos.present('postalcode', '12345')
Esempio n. 9
0
def _searches(topology_st):
    """
        Add attribute types to schema
    """
    cos = CosTemplates(topology_st.standalone, DEFAULT_SUFFIX)
    for attr, value in LIST_ATTR:
        cos.create(properties={
            'cn': attr,
            'attr' + attr.split('entry')[1][:-1]: value
        })
Esempio n. 10
0
    def create_subtree_policy(self, dn, properties):
        """Creates all entries which are needed for the subtree
        password policy

        :param dn: Entry DN for the subtree pwpolicy
        :type dn: str
        :param properties: A dict with password policy settings
        :type properties: dict

        :returns: PwPolicyEntry instance
        """

        # Verify target dn exists before getting started
        subtree_entry = Account(self._instance, dn)
        if not subtree_entry.exists():
            raise ValueError('Can not create subtree password policy because the target dn does not exist')

        # Create the pwp container if needed
        pwp_containers = nsContainers(self._instance, basedn=dn)
        pwp_container = pwp_containers.ensure_state(properties={'cn': 'nsPwPolicyContainer'})

        # Create policy entry
        pwp_entry = None
        properties['cn'] = 'cn=nsPwPolicyEntry_subtree,%s' % dn
        pwp_entries = PwPolicyEntries(self._instance, pwp_container.dn)
        pwp_entry = pwp_entries.create(properties=properties)
        try:
            # The CoS template entry (nsPwTemplateEntry) that has the pwdpolicysubentry
            # value pointing to the above (nsPwPolicyEntry) entry
            cos_template = None
            cos_templates = CosTemplates(self._instance, pwp_container.dn)
            cos_template = cos_templates.create(properties={'cosPriority': '1',
                                                            'pwdpolicysubentry': pwp_entry.dn,
                                                            'cn': 'cn=nsPwTemplateEntry,%s' % dn})

            # The CoS specification entry at the subtree level
            cos_pointer_defs = CosPointerDefinitions(self._instance, dn)
            cos_pointer_defs.create(properties={'cosAttribute': 'pwdpolicysubentry default operational',
                                                'cosTemplateDn': cos_template.dn,
                                                'cn': 'nsPwPolicy_CoS'})
        except ldap.LDAPError as e:
            # Something went wrong, remove what we have done
            if pwp_entry is not None:
                pwp_entry.delete()
            if cos_template is not None:
                cos_template.delete()
            raise e

        # make sure that local policies are enabled
        self.set_global_policy({'nsslapd-pwpolicy-local': 'on'})

        return pwp_entry
Esempio n. 11
0
def test_indexing(topo, _create_entries, real_value):
    """Test positive index filters

    :id: 7337589a-91ae-11e9-ad44-8c16451d917b
    :parametrized: yes
    :setup: Standalone
    :steps:
        1. Try to pass filter rules as per the condition .
    :expected results:
        1. Pass
    """
    cos = CosTemplates(topo.standalone, DEFAULT_SUFFIX, rdn='ou=People')
    assert cos.filter(real_value)
Esempio n. 12
0
def test_do_extensible_search(topology_st, _create_entries, attr, value):
    """Match filter and output.

    :id: abe3e6dd-9ecc-11e8-adf0-8c16451d917c
    :parametrized: yes
    :setup: Standalone
    :steps:
        1. Filer output should match the exact value given.
    :expected results:
        1. Pass
    """
    cos = CosTemplates(topology_st.standalone, DEFAULT_SUFFIX)
    assert len(cos.filter(attr)) == value
Esempio n. 13
0
def test_indexing_negative(topo, _create_entries, real_value):
    """Test negative index filters

    :id: 7e19deae-91ae-11e9-900c-8c16451d917b
    :parametrized: yes
    :setup: Standalone
    :steps:
        1. Try to pass negative filter rules as per the condition .
    :expected results:
        1. Fail
    """
    cos = CosTemplates(topo.standalone, DEFAULT_SUFFIX, rdn='ou=People')
    assert not cos.filter(real_value)
Esempio n. 14
0
def _create_entries(topology_st):
    """
    Add attribute types to schema and Create filter
    entries(Entry with extensibleObject)
    """
    for attribute in ATTR:
        Schema(topology_st.standalone).add('attributetypes', attribute)
    cos = CosTemplates(topology_st.standalone, DEFAULT_SUFFIX)
    # Entry with extensibleObject
    for attr, value in LIST_ATTR_TO_CREATE:
        cos.create(properties={
            'cn': attr,
            'attr' + attr.split('entry')[1][:-1]: value
        })
Esempio n. 15
0
    def lock(self):
        """Set the entry dn to nsDisabledRole and ensure it exists"""

        current_status = self.status()
        if current_status["state"] == RoleState.DIRECTLY_LOCKED:
            raise ValueError(
                f"Role is already {current_status['state'].describe()}")

        inst = self._instance

        mapping_trees = MappingTrees(inst)
        root_suffix = ""
        root_suffix = mapping_trees.get_root_suffix_by_entry(self.dn)

        if root_suffix:
            managed_roles = ManagedRoles(inst, root_suffix)
            managed_role = managed_roles.ensure_state(
                properties={"cn": "nsManagedDisabledRole"})
            nested_roles = NestedRoles(inst, root_suffix)
            try:
                disabled_role = nested_roles.get("nsDisabledRole")
            except ldap.NO_SUCH_OBJECT:
                # We don't use "ensure_state" because we want to preserve the existing attributes
                disabled_role = nested_roles.create(properties={
                    "cn": "nsDisabledRole",
                    "nsRoleDN": managed_role.dn
                })
            disabled_role.add("nsRoleDN", self.dn)

            inact_containers = nsContainers(inst, basedn=root_suffix)
            inact_container = inact_containers.ensure_state(
                properties={'cn': 'nsAccountInactivationTmp'})

            cos_templates = CosTemplates(inst, inact_container.dn)
            cos_templates.ensure_state(
                properties={
                    'cosPriority': '1',
                    'nsAccountLock': 'true',
                    'cn': f'{disabled_role.dn}'
                })

            cos_classic_defs = CosClassicDefinitions(inst, root_suffix)
            cos_classic_defs.ensure_state(
                properties={
                    'cosAttribute': 'nsAccountLock operational',
                    'cosSpecifier': 'nsRole',
                    'cosTemplateDn': inact_container.dn,
                    'cn': 'nsAccountInactivation_cos'
                })
Esempio n. 16
0
    def is_subtree_policy(self, dn):
        """Check if the entry has a subtree password policy.  If we can find a
        template entry it is subtree policy

        :param dn: Entry DN with PwPolicy set up
        :type dn: str

        :returns: True if the entry has a subtree policy, False otherwise
        """
        cos_templates = CosTemplates(self._instance, 'cn=nsPwPolicyContainer,{}'.format(dn))
        try:
            cos_templates.get('cn=nsPwTemplateEntry,%s' % dn)
            return True
        except:
            return False
Esempio n. 17
0
def test_search_positive_negative(topology_st, _create_entries):
    """Filters with positive and with no output.

    :id: abe3e6dd-9ecc-12e8-adf0-8c16451d917b
    :parametrized: yes
    :setup: Standalone
    :steps:
        1.For valid filer output should match the exact value given.
        2. For invalid filter there should not be any output.
    :expected results:
        1. Pass
        2. Pass
    """
    cos = CosTemplates(topology_st.standalone, DEFAULT_SUFFIX)
    for attr, value, negative_filter in FILTER_VALUES:
        assert len(cos.filter(attr)) == value
        assert not cos.filter(negative_filter)
Esempio n. 18
0
def test_match_count(topology_st, _searches, attr, po_value, ne_attr):
    """Search for an attribute with that matching rule with an assertion
    value that should match

    :id: 00276180-b902-11e9-bff2-8c16451d917b
    :parametrized: yes
    :setup: Standalone
    :steps:
        1. Filter rules as per the condition and assert the no of output.
        2. Negative filter with no outputs.
    :expected results:
        1. Pass
        2. Pass
    """
    cos = CosTemplates(topology_st.standalone, DEFAULT_SUFFIX)
    assert len(cos.filter(attr)) == po_value
    assert not cos.filter(ne_attr)
Esempio n. 19
0
def test_indexing_schema(topo, _create_entries):
    """Test with schema

    :id: 67a2179a-91ae-11e9-9a33-8c16451d917b
    :setup: Standalone
    :steps:
        1. Add attribute types to Schema.
        2. Try to pass filter rules as per the condition .
    :expected results:
        1. Pass
        2. Pass
    """
    cos = CosTemplates(topo.standalone, DEFAULT_SUFFIX, rdn='ou=People')
    Schema(topo.standalone).add('attributetypes',
                                "( 8.9.10.11.12.13.14.15 NAME 'myintattr' DESC 'for integer "
                                "syntax index ordering testing' EQUALITY integerMatch ORDERING "
                                "integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )")
    topo.standalone.restart()
    assert cos.filter("(myintattr>=-18446744073709551617)")
Esempio n. 20
0
    def status(self):
        """Check if role is locked in nsDisabledRole (directly or indirectly)

        :returns: a dict
        """

        inst = self._instance
        disabled_roles = {}
        try:
            mapping_trees = MappingTrees(inst)
            root_suffix = mapping_trees.get_root_suffix_by_entry(self.dn)
            roles = Roles(inst, root_suffix)
            disabled_roles = roles.get_disabled_roles()
            nested_roles = NestedRoles(inst, root_suffix)
            disabled_role = nested_roles.get("nsDisabledRole")
            inact_containers = nsContainers(inst, basedn=root_suffix)
            inact_container = inact_containers.get('nsAccountInactivationTmp')

            cos_templates = CosTemplates(inst, inact_container.dn)
            cos_template = cos_templates.get(f'{disabled_role.dn}')
            cos_template.present('cosPriority', '1')
            cos_template.present('nsAccountLock', 'true')

            cos_classic_defs = CosClassicDefinitions(inst, root_suffix)
            cos_classic_def = cos_classic_defs.get('nsAccountInactivation_cos')
            cos_classic_def.present('cosAttribute',
                                    'nsAccountLock operational')
            cos_classic_def.present('cosTemplateDn', inact_container.dn)
            cos_classic_def.present('cosSpecifier', 'nsRole')
        except ldap.NO_SUCH_OBJECT:
            return self._format_status_message(RoleState.PROBABLY_ACTIVATED)

        for role, parent in disabled_roles.items():
            if str.lower(self.dn) == str.lower(role.dn):
                if parent is None:
                    return self._format_status_message(
                        RoleState.DIRECTLY_LOCKED)
                else:
                    return self._format_status_message(
                        RoleState.INDIRECTLY_LOCKED, parent)

        return self._format_status_message(RoleState.ACTIVATED)
Esempio n. 21
0
def _create_entries(topo):
    """
    Will create necessary users for this script.
    """
    # Creating Users
    users_people = UserAccounts(topo.standalone, DEFAULT_SUFFIX)

    for count in range(3):
        users_people.create(properties={
            'ou': ['Accounting', 'People'],
            'cn': f'User {count}F',
            'sn': f'{count}' * 16,
            'givenname': 'FFFFFFFFFFFFFFFF',
            'uid': f'user{count}F',
            'mail': f'user{count}[email protected]',
            'manager': f'uid=user{count}F,ou=People,{DEFAULT_SUFFIX}',
            'userpassword': PW_DM,
            'homeDirectory': '/home/' + f'user{count}F',
            'uidNumber': '1000',
            'gidNumber': '2000',
        })

    cos = CosTemplates(topo.standalone, DEFAULT_SUFFIX, rdn='ou=People')
    for user, number, des in [('a', '18446744073709551617', '2^64+1'),
                              ('b', '18446744073709551618', '2^64+1'),
                              ('c', '-18446744073709551617', '-2^64+1'),
                              ('d', '-18446744073709551618', '-2^64+1'),
                              ('e', '0', '0'),
                              ('f', '2', '2'),
                              ('g', '-2', '-2')]:
        cos.create(properties={
            'cn': user,
            'uidnumber': number,
            'gidnumber': number,
            'myintattr': number,
            'description': f'uidnumber value {des} - gidnumber is same but not indexed'
        })
Esempio n. 22
0
def test_valid_invalid_attributes(topology_st, cn_cn, attr, positive,
                                  negative):
    """Test valid and invalid values of attributes
        :id: 7ec19eca-8cfc-11e9-a0df-8c16451d917b
        :setup: Standalone
        :steps:
            1. Create entry with an attribute that uses that matching rule
            2. Delete existing entry
            3. Create entry with an attribute that uses that matching rule providing duplicate
            values that are duplicates according to the equality matching rule.
        :expected results:
            1. Pass
            2. Pass
            3. Fail
    """
    cos = CosTemplates(topology_st.standalone, DEFAULT_SUFFIX)
    cos.create(properties={'cn': cn_cn, attr: positive})
    for entry in cos.list():
        entry.delete()
    with pytest.raises(ldap.TYPE_OR_VALUE_EXISTS):
        cos.create(properties={'cn': cn_cn, attr: negative})
Esempio n. 23
0
def test_ignore_virtual_attrs(topo):
    """Test nsslapd-ignore-virtual-attrs configuration attribute

    :id: 9915d71b-2c71-4ac0-91d7-92655d53541b
    :setup: Standalone instance
    :steps:
         1. Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config
         2. Check the default value of attribute nsslapd-ignore-virtual-attrs should be OFF
         3. Set the valid values i.e. on/ON and off/OFF for nsslapd-ignore-virtual-attrs
         4. Set invalid value for attribute nsslapd-ignore-virtual-attrs
         5. Set nsslapd-ignore-virtual-attrs=off
         6. Add cosPointer, cosTemplate and test entry to default suffix, where virtual attribute is postal code
         7. Test if virtual attribute i.e. postal code shown in test entry while nsslapd-ignore-virtual-attrs: off
         8. Set nsslapd-ignore-virtual-attrs=on
         9. Test if virtual attribute i.e. postal code not shown while nsslapd-ignore-virtual-attrs: on
    :expectedresults:
         1. This should be successful
         2. This should be successful
         3. This should be successful
         4. This should fail
         5. This should be successful
         6. This should be successful
         7. Postal code should be present
         8. This should be successful
         9. Postal code should not be present
    """

    log.info("Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config")
    assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs')

    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be OFF")
    assert topo.standalone.config.get_attr_val_utf8('nsslapd-ignore-virtual-attrs') == "off"

    log.info("Set the valid values i.e. on/ON and off/OFF for nsslapd-ignore-virtual-attrs")
    for attribute_value in ['on', 'off', 'ON', 'OFF']:
        topo.standalone.config.set('nsslapd-ignore-virtual-attrs', attribute_value)
        assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs', attribute_value)

    log.info("Set invalid value for attribute nsslapd-ignore-virtual-attrs")
    with pytest.raises(ldap.OPERATIONS_ERROR):
        topo.standalone.config.set('nsslapd-ignore-virtual-attrs', 'invalid_value')

    cos_template_properties = {
        'cn': 'cosTemplateExample',
        'postalcode': '117'
    }
    cos_templates = CosTemplates(topo.standalone, DEFAULT_SUFFIX, 'ou=People')
    test_cos_template = cos_templates.create(properties=cos_template_properties)

    log.info("Add cosPointer, cosTemplate and test entry to default suffix, where virtual attribute is postal code")
    cos_pointer_properties = {
        'cn': 'cosPointer',
        'description': 'cosPointer example',
        'cosTemplateDn': 'cn=cosTemplateExample,ou=People,dc=example,dc=com',
        'cosAttribute': 'postalcode',
    }
    cos_pointer_definitions = CosPointerDefinitions(topo.standalone, DEFAULT_SUFFIX, 'ou=People')
    test_cos_pointer_definition = cos_pointer_definitions.create(properties=cos_pointer_properties)

    test_users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
    test_user = test_users.create(properties=TEST_USER_PROPERTIES)

    log.info("Test if virtual attribute i.e. postal code shown in test entry while nsslapd-ignore-virtual-attrs: off")
    assert test_user.present('postalcode', '117')

    log.info("Set nsslapd-ignore-virtual-attrs=on")
    topo.standalone.config.set('nsslapd-ignore-virtual-attrs', 'on')

    log.info("Test if virtual attribute i.e. postal code not shown while nsslapd-ignore-virtual-attrs: on")
    assert not test_user.present('postalcode', '117')
Esempio n. 24
0
    def status(self):
        """Check if account is locked by Account Policy plugin or
        nsAccountLock (directly or indirectly)

        :returns: a dict in a format -
                  {"status": status, "params": activity_data, "calc_time": epoch_time}
        """

        inst = self._instance

        # Fetch Account Policy data if its enabled
        plugin = AccountPolicyPlugin(inst)
        state_attr = ""
        alt_state_attr = ""
        limit = ""
        spec_attr = ""
        limit_attr = ""
        process_account_policy = False
        try:
            process_account_policy = plugin.status()
        except IndexError:
            self._log.debug(
                "The bound user doesn't have rights to access Account Policy settings. Not checking."
            )

        if process_account_policy:
            config_dn = plugin.get_attr_val_utf8("nsslapd-pluginarg0")
            config = AccountPolicyConfig(inst, config_dn)
            config_settings = config.get_attrs_vals_utf8([
                "stateattrname", "altstateattrname", "specattrname",
                "limitattrname"
            ])
            state_attr = self._dict_get_with_ignore_indexerror(
                config_settings, "stateattrname")
            alt_state_attr = self._dict_get_with_ignore_indexerror(
                config_settings, "altstateattrname")
            spec_attr = self._dict_get_with_ignore_indexerror(
                config_settings, "specattrname")
            limit_attr = self._dict_get_with_ignore_indexerror(
                config_settings, "limitattrname")

            mapping_trees = MappingTrees(inst)
            root_suffix = mapping_trees.get_root_suffix_by_entry(self.dn)
            cos_entries = CosTemplates(inst, root_suffix)
            accpol_entry_dn = ""
            for cos in cos_entries.list():
                if cos.present(spec_attr):
                    accpol_entry_dn = cos.get_attr_val_utf8_l(spec_attr)
            if accpol_entry_dn:
                accpol_entry = AccountPolicyEntry(inst, accpol_entry_dn)
            else:
                accpol_entry = config
            limit = accpol_entry.get_attr_val_utf8_l(limit_attr)

        # Fetch account data
        account_data = self.get_attrs_vals_utf8([
            "createTimestamp", "modifyTimeStamp", "nsAccountLock", state_attr
        ])

        last_login_time = self._dict_get_with_ignore_indexerror(
            account_data, state_attr)
        if not last_login_time:
            last_login_time = self._dict_get_with_ignore_indexerror(
                account_data, alt_state_attr)

        create_time = self._dict_get_with_ignore_indexerror(
            account_data, "createTimestamp")
        modify_time = self._dict_get_with_ignore_indexerror(
            account_data, "modifyTimeStamp")

        acct_roles = self.get_attr_vals_utf8_l("nsRole")
        mapping_trees = MappingTrees(inst)
        root_suffix = ""
        try:
            root_suffix = mapping_trees.get_root_suffix_by_entry(self.dn)
        except ldap.NO_SUCH_OBJECT:
            self._log.debug(
                "The bound user doesn't have rights to access disabled roles settings. Not checking."
            )
        if root_suffix:
            roles = Roles(inst, root_suffix)
            try:
                disabled_roles = roles.get_disabled_roles()

                # Locked indirectly through a role
                locked_indirectly_role_dn = ""
                for role in acct_roles:
                    if str.lower(role) in [
                            str.lower(role.dn)
                            for role in disabled_roles.keys()
                    ]:
                        locked_indirectly_role_dn = role
                if locked_indirectly_role_dn:
                    return self._format_status_message(
                        AccountState.INDIRECTLY_LOCKED, create_time,
                        modify_time, last_login_time, limit,
                        locked_indirectly_role_dn)
            except ldap.NO_SUCH_OBJECT:
                pass

        # Locked directly
        if self._dict_get_with_ignore_indexerror(account_data,
                                                 "nsAccountLock") == "true":
            return self._format_status_message(AccountState.DIRECTLY_LOCKED,
                                               create_time, modify_time,
                                               last_login_time, limit)

        # Locked indirectly through Account Policy plugin
        if process_account_policy and last_login_time:
            # Now check the Account Policy Plugin inactivity limits
            remaining_time = float(limit) - (time.mktime(
                time.gmtime()) - gentime_to_posix_time(last_login_time))
            if remaining_time <= 0:
                return self._format_status_message(
                    AccountState.INACTIVITY_LIMIT_EXCEEDED, create_time,
                    modify_time, last_login_time, limit)
        # All checks are passed - we are active
        return self._format_status_message(AccountState.ACTIVATED, create_time,
                                           modify_time, last_login_time, limit)
Esempio n. 25
0
 def get_cos_templates(self):
     return CosTemplates(self._instance, self._dn).list()
Esempio n. 26
0
    def delete_local_policy(self, dn):
        """Delete a local password policy entry

        :param dn: Entry DN for the local pwpolicy
        :type dn: str
        """

        subtree = False

        # Verify target dn exists, and has a policy
        entry = Account(self._instance, dn)
        if not entry.exists():
            raise ValueError('The target entry dn does not exist')
        pwp_entry = self.get_pwpolicy_entry(entry.dn)

        # Subtree or user policy?
        if self.is_subtree_policy(entry.dn):
            parentdn = dn
            subtree = True
        else:
            dn_comps = ldap.dn.explode_dn(dn)
            dn_comps.pop(0)
            parentdn = ",".join(dn_comps)

        # Starting deleting the policy, ignore the parts that might already have been removed
        pwp_container = nsContainer(self._instance,
                                    'cn=nsPwPolicyContainer,%s' % parentdn)
        if subtree:
            try:
                # Delete template
                cos_templates = CosTemplates(self._instance, pwp_container.dn)
                cos_template = cos_templates.get('cn=nsPwTemplateEntry,%s' %
                                                 dn)
                cos_template.delete()
            except ldap.NO_SUCH_OBJECT:
                # Already deleted
                pass
            try:
                # Delete definition
                cos_pointer_def = CosPointerDefinition(
                    self._instance, 'cn=nsPwPolicy_CoS,%s' % dn)
                cos_pointer_def.delete()
            except ldap.NO_SUCH_OBJECT:
                # Already deleted
                pass
        else:
            try:
                # Cleanup user entry
                entry.remove("pwdpolicysubentry", pwp_entry.dn)
            except ldap.NO_SUCH_ATTRIBUTE:
                # Policy already removed from user
                pass

        # Remove the local policy
        try:
            pwp_entry.delete()
        except ldap.NO_SUCH_OBJECT:
            # Already deleted
            pass

        try:
            pwp_container.delete()
        except (ldap.NOT_ALLOWED_ON_NONLEAF, ldap.NO_SUCH_OBJECT):
            # There are other policies still using this container, no problem
            pass