Ejemplo n.º 1
0
    def get_pwpolicy_entry(self, dn):
        """Get a local password policy entry

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

        :returns: PwPolicyEntry instance
        """

        entry = Account(self._instance, dn)
        if not entry.exists():
            raise ValueError(
                'Can not get the password policy entry because the target dn does not exist'
            )

        # Get the parent DN
        dn_comps = ldap.dn.explode_dn(entry.dn)
        dn_comps.pop(0)
        parentdn = ",".join(dn_comps)

        # Get the parent's policies
        pwp_entries = PwPolicyEntries(self._instance, parentdn)
        policies = pwp_entries.list()
        for policy in policies:
            dn_comps = ldap.dn.explode_dn(policy.get_attr_val_utf8_l('cn'))
            dn_comps.pop(0)
            pwp_dn = ",".join(dn_comps)
            if pwp_dn == dn.lower():
                # This DN does have a policy associated with it
                return policy

        # Did not find a policy for this entry
        raise ValueError("No password policy was found for this entry")
Ejemplo n.º 2
0
def list_policies(inst, basedn, log, args):
    log = log.getChild('list_policies')
    targetdn = args.DN[0]

    if args.json:
        result = {'type': 'list', 'items': []}
    else:
        result = ""

    # Verify target dn exists before getting started
    user_entry = Account(inst, args.DN[0])
    if not user_entry.exists():
        raise ValueError('The target entry dn does not exist')

    # User pwpolicy entry is under the container that is under the parent,
    # so we need to go one level up
    pwp_entries = PwPolicyEntries(inst, targetdn)
    for pwp_entry in pwp_entries.list():
        dn_comps = ldap.dn.explode_dn(pwp_entry.get_attr_val_utf8_l('cn'))
        dn_comps.pop(0)
        entrydn = ",".join(dn_comps)
        policy_type = _get_policy_type(inst, entrydn)
        if args.json:
            result['items'].append([entrydn, policy_type])
        else:
            result += "%s (%s)\n" % (entrydn, policy_type.lower())

    if args.json:
        print(json.dumps(result))
    else:
        print(result)
Ejemplo n.º 3
0
def list_policies(inst, basedn, log, args):
    log = log.getChild('list_policies')

    if args.DN is None:
        # list all the password policies for all the backends
        targetdns = []
        backends = Backends(inst).list()
        for backend in backends:
            targetdns.append(backend.get_suffix())
    else:
        targetdns = [args.DN]

    if args.json:
        result = {'type': 'list', 'items': []}
    else:
        result = ""

    for targetdn in targetdns:
        # Verify target dn exists before getting started
        user_entry = Account(inst, targetdn)
        if not user_entry.exists():
            raise ValueError('The target entry dn does not exist')

        # User pwpolicy entry is under the container that is under the parent,
        # so we need to go one level up
        pwp_entries = PwPolicyEntries(inst, targetdn)
        pwp_manager = PwPolicyManager(inst)
        attr_list = list(pwp_manager.arg_to_attr.values())

        for pwp_entry in pwp_entries.list():
            dn_comps = ldap.dn.explode_dn(pwp_entry.get_attr_val_utf8_l('cn'))
            dn_comps.pop(0)
            entrydn = ",".join(dn_comps)
            policy_type = _get_policy_type(inst, entrydn)
            all_attrs = pwp_entry.get_attrs_vals_utf8(attr_list)
            attrs = {k: v for k, v in all_attrs.items() if len(v) > 0}
            if args.json:
                result['items'].append(
                    {
                        "dn": pwp_entry.dn,
                        "targetdn": entrydn,
                        "pwp_type": policy_type,
                        "basedn": pwp_entry.get_basedn(),
                        "attrs": attrs
                    }
                )
            else:
                result += "%s (%s)\n" % (entrydn, policy_type.lower())

    if args.json:
        print(json.dumps(result, indent=4))
    else:
        print(result)
Ejemplo n.º 4
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
Ejemplo n.º 5
0
    def create_user_policy(self, dn, properties):
        """Creates all entries which are needed for the user
        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
        user_entry = Account(self._instance, dn)
        if not user_entry.exists():
            raise ValueError(
                'Can not create user password policy because the target dn does not exist'
            )

        dn_comps = ldap.dn.explode_dn(user_entry.dn)
        dn_comps.pop(0)
        parentdn = ",".join(dn_comps)

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

        # Create policy entry
        properties['cn'] = 'cn=nsPwPolicyEntry_user,%s' % dn
        pwp_entries = PwPolicyEntries(self._instance, pwp_container.dn)
        pwp_entry = pwp_entries.create(properties=properties)
        try:
            # Add policy to the entry
            user_entry.replace('pwdpolicysubentry', pwp_entry.dn)
        except ldap.LDAPError as e:
            # failure, undo what we have done
            pwp_entry.delete()
            raise e

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

        return pwp_entry
Ejemplo n.º 6
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
Ejemplo n.º 7
0
def test_chaining_paged_search(topology):
    """ Test paged search through the chaining db. This
    would cause a SIGSEGV with paged search which could
    be triggered by SSSD.

    :id: 7b29b1f5-26cf-49fa-9fe7-ee29a1408633
    :setup: Two standalones in chaining.
    :steps:
        1. Configure chaining between the nodes
        2. Do a chaining search (no page) to assert it works
        3. Do a paged search through chaining.

    :expectedresults:
        1. Success
        2. Success
        3. Success
    """
    st1 = topology.ins["standalone1"]
    st2 = topology.ins["standalone2"]

    ### We setup so that st1 -> st2

    # Clear all the BE in st1
    bes1 = Backends(st1)
    for be in bes1.list():
        be.delete()

    # Setup st1 to chain to st2
    chain_plugin_1 = ChainingBackendPlugin(st1)
    chain_plugin_1.enable()

    chains = ChainingLinks(st1)
    chain = chains.create(
        properties={
            'cn': 'demochain',
            'nsslapd-suffix': DEFAULT_SUFFIX,
            'nsmultiplexorbinddn': '',
            'nsmultiplexorcredentials': '',
            'nsfarmserverurl': st2.toLDAPURL(),
        })

    mts = MappingTrees(st1)
    # Due to a bug in lib389, we need to delete and recreate the mt.
    for mt in mts.list():
        mt.delete()
    mts.ensure_state(
        properties={
            'cn': DEFAULT_SUFFIX,
            'nsslapd-state': 'backend',
            'nsslapd-backend': 'demochain',
        })
    # Restart to enable
    st1.restart()

    # Get an anonymous connection.
    anon = Account(st1, dn='')
    anon_conn = anon.bind(password='')

    # Now do a search from st1 -> st2
    accs_1 = Accounts(anon_conn, DEFAULT_SUFFIX)
    assert len(accs_1.list()) > 0

    # Allow time to attach lldb if needed.
    # import time
    # print("🔥🔥🔥")
    # time.sleep(45)

    # Now do a *paged* search from st1 -> st2
    assert len(accs_1.list(paged_search=2, paged_critical=False)) > 0
Ejemplo n.º 8
0
def test_binddn_tracking(topo, _create_inital):
    """Test Managed Entries basic functionality

    :id: ea2ddfd4-aaec-11ea-8416-8c16451d917b
    :setup: Standalone Instance
    :steps:
        1. Set nsslapd-plugin-binddn-tracking attribute under cn=config
        2. Add user
        3. Managed Entry Plugin runs against managed entries upon any update without validating
        4. verify creation of User Private Group with its time stamp value
        5. Modify the SN attribute which is not mapped with managed entry
        6. run ModRDN operation and check the User Private group
        7. Check the time stamp of UPG should be changed now
        8. Check the creatorsname should be user dn and internalCreatorsname should be plugin name
        9. Check if a managed group entry was created
    :expected results:
        1. Success
        2. Success
        3. Success
        4. Success
        5. Success
        6. Success
        7. Success
        8. Success
        9. Success
    """
    config = Config(topo.standalone)
    # set nsslapd-plugin-binddn-tracking attribute under cn=config
    config.replace('nsslapd-plugin-binddn-tracking', 'on')
    # Add user
    user = UserAccounts(topo.standalone,
                        f'cn=Users,{DEFAULT_SUFFIX}',
                        rdn=None).create_test_user()
    assert user.get_attr_val_utf8(
        'mepManagedEntry') == f'cn=test_user_1000,cn=Groups,{DEFAULT_SUFFIX}'
    entry = Account(topo.standalone,
                    f'cn=test_user_1000,cn=Groups,{DEFAULT_SUFFIX}')
    # Managed Entry Plugin runs against managed entries upon any update without validating
    # verify creation of User Private Group with its time stamp value
    stamp1 = entry.get_attr_val_utf8('modifyTimestamp')
    user.replace('sn', 'NewSN_modified')
    stamp2 = entry.get_attr_val_utf8('modifyTimestamp')
    # Modify the SN attribute which is not mapped with managed entry
    # Check the time stamp of UPG should not be changed
    assert stamp1 == stamp2
    time.sleep(1)
    # run ModRDN operation and check the User Private group
    user.rename(new_rdn='uid=UserNewRDN',
                newsuperior='cn=Users,dc=example,dc=com')
    assert user.get_attr_val_utf8(
        'mepManagedEntry') == f'cn=UserNewRDN,cn=Groups,{DEFAULT_SUFFIX}'
    entry = Account(topo.standalone,
                    f'cn=UserNewRDN,cn=Groups,{DEFAULT_SUFFIX}')
    stamp3 = entry.get_attr_val_utf8('modifyTimestamp')
    # Check the time stamp of UPG should be changed now
    assert stamp2 != stamp3
    time.sleep(1)
    user.replace('gidNumber', '1')
    stamp4 = entry.get_attr_val_utf8('modifyTimestamp')
    assert stamp4 != stamp3
    # Check the creatorsname should be user dn and internalCreatorsname should be plugin name
    assert entry.get_attr_val_utf8('creatorsname') == 'cn=directory manager'
    assert entry.get_attr_val_utf8(
        'internalCreatorsname') == 'cn=Managed Entries,cn=plugins,cn=config'
    assert entry.get_attr_val_utf8('modifiersname') == 'cn=directory manager'
    user.delete()
    config.replace('nsslapd-plugin-binddn-tracking', 'off')
Ejemplo n.º 9
0
def test_mentry01(topo, _create_inital):
    """Test Managed Entries basic functionality

    :id: 9b87493b-0493-46f9-8364-6099d0e5d806
    :setup: Standalone Instance
    :steps:
        1. Check the plug-in status
        2. Add Template and definition entry
        3. Add our org units
        4. Add users with PosixAccount ObjectClass and verify creation of User Private Group
        5. Disable the plug-in and check the status
        6. Enable the plug-in and check the status the plug-in is disabled and creation of UPG should fail
        7. Add users with PosixAccount ObjectClass and verify creation of User Private Group
        8. Add users, run ModRDN operation and check the User Private group
        9. Add users, run LDAPMODIFY to change the gidNumber and check the User Private group
        10. Checking whether creation of User Private group fails for existing group entry
        11. Checking whether adding of posixAccount objectClass to existing user creates UPG
        12. Running ModRDN operation and checking the user private groups mepManagedBy attribute
        13. Deleting mepManagedBy attribute and running ModRDN operation to check if it creates a new UPG
        14. Change the RDN of template entry, DSA Unwilling to perform error expected
        15. Change the RDN of cn=Users to cn=TestUsers and check UPG are deleted
    :expected results:
        1. Success
        2. Success
        3. Success
        4. Success
        5. Success
        6. Success
        7. Success
        8. Success
        9. Success
        10. Success
        11. Success
        12. Success
        13. Success
        14. Fail(Unwilling to perform )
        15. Success
    """
    # Check the plug-in status
    mana = ManagedEntriesPlugin(topo.standalone)
    assert mana.status()

    # Add Template and definition entry
    org1 = OrganizationalUnits(
        topo.standalone, DEFAULT_SUFFIX).create(properties={'ou': 'Users'})
    org2 = OrganizationalUnit(topo.standalone, f'ou=Groups,{DEFAULT_SUFFIX}')
    meps = MEPTemplates(topo.standalone, DEFAULT_SUFFIX)
    mep_template1 = meps.create(
        properties={
            'cn':
            'UPG Template1',
            'mepRDNAttr':
            'cn',
            'mepStaticAttr':
            'objectclass: posixGroup',
            'mepMappedAttr':
            'cn: $uid|gidNumber: $gidNumber|description: User private group for $uid'
            .split('|')
        })
    conf_mep = MEPConfigs(topo.standalone)
    conf_mep.create(
        properties={
            'cn': 'UPG Definition2',
            'originScope': org1.dn,
            'originFilter': 'objectclass=posixaccount',
            'managedBase': org2.dn,
            'managedTemplate': mep_template1.dn
        })

    # Add users with PosixAccount ObjectClass and verify creation of User Private Group
    user = UserAccounts(topo.standalone,
                        f'ou=Users,{DEFAULT_SUFFIX}',
                        rdn=None).create_test_user()
    assert user.get_attr_val_utf8(
        'mepManagedEntry') == f'cn=test_user_1000,ou=Groups,{DEFAULT_SUFFIX}'

    # Disable the plug-in and check the status
    mana.disable()
    user.delete()
    topo.standalone.restart()

    # Add users with PosixAccount ObjectClass when the plug-in is disabled and creation of UPG should fail
    user = UserAccounts(topo.standalone,
                        f'ou=Users,{DEFAULT_SUFFIX}',
                        rdn=None).create_test_user()
    assert not user.get_attr_val_utf8('mepManagedEntry')

    # Enable the plug-in and check the status
    mana.enable()
    user.delete()
    topo.standalone.restart()

    # Add users with PosixAccount ObjectClass and verify creation of User Private Group
    user = UserAccounts(topo.standalone,
                        f'ou=Users,{DEFAULT_SUFFIX}',
                        rdn=None).create_test_user()
    assert user.get_attr_val_utf8(
        'mepManagedEntry') == f'cn=test_user_1000,ou=Groups,{DEFAULT_SUFFIX}'

    # Add users, run ModRDN operation and check the User Private group
    # Add users, run LDAPMODIFY to change the gidNumber and check the User Private group
    user.rename(new_rdn='uid=UserNewRDN',
                newsuperior='ou=Users,dc=example,dc=com')
    assert user.get_attr_val_utf8(
        'mepManagedEntry') == f'cn=UserNewRDN,ou=Groups,{DEFAULT_SUFFIX}'
    user.replace('gidNumber', '20209')
    entry = Account(topo.standalone,
                    f'cn=UserNewRDN,ou=Groups,{DEFAULT_SUFFIX}')
    assert entry.get_attr_val_utf8('gidNumber') == '20209'
    user.replace_many(('sn', 'new_modified_sn'), ('gidNumber', '31309'))
    assert entry.get_attr_val_utf8('gidNumber') == '31309'
    user.delete()

    # Checking whether creation of User Private group fails for existing group entry
    Groups(topo.standalone, f'ou=Groups,{DEFAULT_SUFFIX}',
           rdn=None).create(properties={'cn': 'MENTRY_14'})
    user = UserAccounts(topo.standalone,
                        f'ou=Users,{DEFAULT_SUFFIX}',
                        rdn=None).create_test_user()
    with pytest.raises(ldap.NO_SUCH_OBJECT):
        entry.status()
    user.delete()

    # Checking whether adding of posixAccount objectClass to existing user creates UPG
    # Add Users without posixAccount objectClass
    users = WithObjectClass(topo.standalone,
                            f'uid=test_test, ou=Users,{DEFAULT_SUFFIX}')
    user_properties1 = {
        'uid': 'test_test',
        'cn': 'test',
        'sn': 'test',
        'mail': '*****@*****.**',
        'telephoneNumber': '123'
    }
    user = users.create(properties=user_properties1)
    assert not user.get_attr_val_utf8('mepManagedEntry')

    # Add posixAccount objectClass
    user.replace_many(
        ('objectclass', ['top', 'person', 'inetorgperson', 'posixAccount']),
        ('homeDirectory', '/home/ok'), ('uidNumber', '61603'),
        ('gidNumber', '61603'))
    assert not user.get_attr_val_utf8('mepManagedEntry')
    user = UserAccounts(topo.standalone,
                        f'ou=Users,{DEFAULT_SUFFIX}',
                        rdn=None).create_test_user()
    entry = Account(topo.standalone,
                    'cn=test_user_1000,ou=Groups,dc=example,dc=com')

    # Add inetuser objectClass
    user.replace_many(('objectclass', [
        'top', 'account', 'posixaccount', 'inetOrgPerson',
        'organizationalPerson', 'nsMemberOf', 'nsAccount', 'person',
        'mepOriginEntry', 'inetuser'
    ]), ('memberOf', entry.dn))
    assert entry.status()
    user.delete()
    user = UserAccounts(topo.standalone,
                        f'ou=Users,{DEFAULT_SUFFIX}',
                        rdn=None).create_test_user()
    entry = Account(topo.standalone,
                    'cn=test_user_1000,ou=Groups,dc=example,dc=com')

    # Add groupofNames objectClass
    user.replace_many(('objectclass', [
        'top', 'account', 'posixaccount', 'inetOrgPerson',
        'organizationalPerson', 'nsMemberOf', 'nsAccount', 'person',
        'mepOriginEntry', 'groupofNames'
    ]), ('memberOf', user.dn))
    assert entry.status()

    # Running ModRDN operation and checking the user private groups mepManagedBy
    # attribute was also reset because the modrdn on the origin will do a modrdn
    # on checkManagedEntry to match the new rdn value of the origin entry
    checkManagedEntry = UserAccounts(topo.standalone,
                                     f'ou=Groups,{DEFAULT_SUFFIX}',
                                     rdn=None)
    check_entry = checkManagedEntry.create(
        properties={
            'objectclass': ['top', 'extensibleObject'],
            'uid': 'CheckModRDN',
            'uidNumber': '12',
            'gidNumber': '12',
            'homeDirectory': '/home',
            'sn': 'tmp',
            'cn': 'tmp',
        })
    user.replace('mepManagedEntry', check_entry.dn)
    user.rename(new_rdn='uid=UserNewRDN',
                newsuperior='ou=Users,dc=example,dc=com')
    assert user.get_attr_val_utf8_l(
        'mepManagedEntry'
    ) == f'cn=UserNewRDN,ou=Groups,{DEFAULT_SUFFIX}'.lower()

    # Deleting mepManagedBy attribute and running ModRDN operation to check if it creates a new UPG
    user.remove('mepManagedEntry', f'cn=UserNewRDN,ou=Groups,{DEFAULT_SUFFIX}')
    user.rename(new_rdn='uid=UserNewRDN1',
                newsuperior='ou=Users,dc=example,dc=com')
    assert user.get_attr_val_utf8(
        'mepManagedEntry') == f'cn=UserNewRDN1,ou=Groups,{DEFAULT_SUFFIX}'

    # Change the RDN of template entry, DSA Unwilling to perform error expected
    mep = MEPTemplate(topo.standalone, f'cn=UPG Template,{DEFAULT_SUFFIX}')
    with pytest.raises(ldap.UNWILLING_TO_PERFORM):
        mep.rename(new_rdn='cn=UPG Template2', newsuperior='dc=example,dc=com')

    # Change the RDN of cn=Users to cn=TestUsers and check UPG are deleted
    before = user.get_attr_val_utf8('mepManagedEntry')
    user.rename(new_rdn='uid=Anuj', newsuperior='ou=Users,dc=example,dc=com')
    assert user.get_attr_val_utf8('mepManagedEntry') != before