Esempio n. 1
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
Esempio n. 2
0
class ChainingLink(DSLdapObject):
    """Chaining Backend DSLdapObject with:
    - must attributes = ['cn', 'nsslapd-suffix', 'nsmultiplexorbinddn',
                         'nsmultiplexorcredentials', 'nsfarmserverurl'
    - RDN attribute is 'cn'

    :param instance: An instance
    :type instance: lib389.DirSrv
    :param dn: Entry DN
    :type dn: str
    """

    _must_attributes = ['nsslapd-suffix', 'cn']

    def __init__(self, instance, dn=None, rdn=None):
        super(ChainingLink, self).__init__(instance, dn)
        self._rdn_attribute = 'cn'
        self._must_attributes = [
            'nsslapd-suffix', 'cn', 'nsmultiplexorbinddn',
            'nsmultiplexorcredentials', 'nsfarmserverurl'
        ]
        self._create_objectclasses = [
            'top', 'extensibleObject', BACKEND_OBJECTCLASS_VALUE
        ]
        self._protected = False
        self._basedn = "cn=chaining database,cn=plugins,cn=config"
        self._mts = MappingTrees(self._instance)

    def get_monitor(self):
        """Get a MonitorChaining(DSLdapObject) for the chaining link
        :returns - chaining monitor entry
        """
        return MonitorChaining(instance=self._instance,
                               dn="cn=monitor,%s" % self._dn)

    def del_link(self):
        """
        Remove the link from the parent suffix backend entry
        Delete chaining monitor entry
        Delete chaining entry
        """

        rdn = self.get_attr_val_utf8_l('cn')
        try:
            mt = self._mts.get(selector=rdn)
            mt.delete()
        except ldap.NO_SUCH_OBJECT:
            # Righto, it's already gone! Do nothing ...
            pass

        # Delete the monitoring entry
        monitor = self.get_monitor(rdn)
        monitor.delete()

        # Delete the link
        self.delete()

    def create(self, rdn=None, properties=None, basedn=None):
        """Create the link entry, and the mapping tree entry(if needed)
        """

        # Create chaining entry
        super(ChainingLink, self).create(rdn, properties, basedn)

        # Create mapping tree entry
        dn_comps = ldap.explode_dn(properties['nsslapd-suffix'][0])
        parent_suffix = ','.join(dn_comps[1:])
        mt_properties = {
            'cn': properties['nsslapd-suffix'][0],
            'nsslapd-state': 'backend',
            'nsslapd-backend': properties['cn'][0],
            'nsslapd-parent-suffix': parent_suffix
        }
        try:
            self._mts.ensure_state(properties=mt_properties)
        except ldap.ALREADY_EXISTS:
            pass
def test_chaining_paged_search(topology):
    """ Check that when the chaining target has anonymous access
    disabled that the ping still functions and allows the search
    to continue with an appropriate bind user.

    :id: 00bf31db-d93b-4224-8e70-86abb2d4cd17
    :setup: Two standalones in chaining.
    :steps:
        1. Configure chaining between the nodes
        2. Do a chaining search (w anon allow) to assert it works
        3. Configure anon dis allowed on st2
        4. Restart both
        5. Check search still works

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

    ### We setup so that st1 -> st2

    # Setup a chaining user on st2 to authenticate to.
    sa = ServiceAccounts(st2, DEFAULT_SUFFIX).create(properties = {
        'cn': 'sa',
        'userPassword': PW
    })

    # Add a proxy user.
    sproxy = ServiceAccounts(st2, DEFAULT_SUFFIX).create(properties = {
        'cn': 'proxy',
        'userPassword': PW
    })

    # Add the read and proxy ACI
    dc = Domain(st2, DEFAULT_SUFFIX)
    dc.add('aci',
        f"""(targetattr="objectClass || cn || uid")(version 3.0; acl "Enable sa read"; allow (read, search, compare)(userdn="ldap:///{sa.dn}");)"""
    )
    # Add the proxy ACI
    dc.add('aci',
        f"""(targetattr="*")(version 3.0; acl "Enable proxy access"; allow (proxy)(userdn="ldap:///{sproxy.dn}");)"""
    )

    # 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()

    # Chain with the proxy user.
    chains = ChainingLinks(st1)
    chain = chains.create(properties={
        'cn': 'demochain',
        'nsfarmserverurl': st2.toLDAPURL(),
        'nsslapd-suffix': DEFAULT_SUFFIX,
        'nsmultiplexorbinddn': sproxy.dn,
        'nsmultiplexorcredentials': PW,
        'nsCheckLocalACI': 'on',
        'nsConnectionLife': '30',
    })

    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',
        'nsslapd-distribution-plugin': 'libreplication-plugin',
        'nsslapd-distribution-funct': 'repl_chain_on_update',
    })

    # Enable pwpolicy (Not sure if part of the issue).
    st1.config.set('passwordIsGlobalPolicy', 'on')
    st2.config.set('passwordIsGlobalPolicy', 'on')

    # Restart to enable everything.
    st1.restart()

    # Get a proxy auth connection.
    sa1 = ServiceAccount(st1, sa.dn)
    sa1_conn = sa1.bind(password=PW)

    # Now do a search from st1 -> st2
    sa1_dc = Domain(sa1_conn, DEFAULT_SUFFIX)
    assert sa1_dc.exists()

    # Now on st2 disable anonymous access.
    st2.config.set('nsslapd-allow-anonymous-access', 'rootdse')

    # Stop st2 to force the connection to be dead.
    st2.stop()
    # Restart st1 - this means it must re-do the ping/keepalive.
    st1.restart()

    # do a bind - this should fail, and forces the conn offline.
    with pytest.raises(ldap.OPERATIONS_ERROR):
        sa1.bind(password=PW)

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

    # Bring st2 online.
    st2.start()

    # Wait a bit
    time.sleep(5)

    # Get a proxy auth connection (again)
    sa1_conn = sa1.bind(password=PW)
    # Now do a search from st1 -> st2
    sa1_dc = Domain(sa1_conn, DEFAULT_SUFFIX)
    assert sa1_dc.exists()