Spezielle LDAP Konfiguration

Gibt es Probleme bei der Verbindung mit dem LDAP-Server unter Verwendung eines Connection Pools, so kann man diesen mit folgenden Schritten deaktivieren.

Die aktuelle IdP-Version (3.2.1) basiert auf Ldaptive und benutzt standardmäßig eine sogenannte PooledConnectionFactory.
Das heist im Speziellen, dass Shibboleth eine definierte Anzahl an Verbindungen zum LDAP-Dienst aufrecht erhält.
Vorteil dabei ist, dass zum Zeitpunkt des Logins eines Nutzers nicht erst eine Verbindung zum LDAP aufgebaut werden muss, sondern dieser sich ohne Verzögerung sofort authentifizieren kann. (Performance-Verbesserung)

Wenn aus welchen Gründen auch immer diese Verbindung beendet wird, so registriert Shibboleth dies und baut selbstständig eine neue auf.
Dies kann z.B. auftreten wenn der LDAP-Server die Verbindungen nach einer bestimmten „idleTime“ beendet.
Im Großen und Ganzen kann man dies alles über ein paar Parameter unter conf/ldap.properties steuern.

conf/ldap.properties
# LDAP pool configuration, used for both authn and DN resolution
#idp.pool.LDAP.minSize                          = 3
#idp.pool.LDAP.maxSize                          = 10
#idp.pool.LDAP.validateOnCheckout               = false
#idp.pool.LDAP.validatePeriodically             = true
#idp.pool.LDAP.validatePeriod                   = 300
#idp.pool.LDAP.prunePeriod                      = 300
#idp.pool.LDAP.idleTime                         = 600
#idp.pool.LDAP.blockWaitTime                    = 3000
#idp.pool.LDAP.failFastInitialize               = false

Nun kann es in Einzelfällen jedoch dazu kommen, dass die Verbindung zwar erhalten bleibt, jedoch in einer definierten Zeit keine Antwort vom LDAP zurück kommt. (z.B. bei erhöhtem Load)
Dies führt letztendlich dazu, dass sich Nutzer nicht mehr am IdP einloggen können wenn dieser die maximale Anzahl an Verbindungen erreicht hat.

Ein passender Eintrag in den Logfiles sieht wie folgt aus:

WARN [net.shibboleth.idp.authn.impl.ValidateUsernamePasswordAgainstLDAP:175] - Profile Action ValidateUsernamePasswordAgainstLDAP: Login by centreon produced exception
org.ldaptive.LdapException: javax.naming.NamingException: LDAP response read timed out, timeout used:3000ms.
        at org.ldaptive.provider.ProviderUtils.throwOperationException(ProviderUtils.java:77)
Caused by: javax.naming.NamingException: LDAP response read timed out, timeout used:3000ms.
        at com.sun.jndi.ldap.Connection.readReply(Connection.java:502)

Ältere Versionen vom IdP haben hingegen keine Verbindungen offen gehalten, sondern diese erst geöffnet, wenn sich ein Nutzer einloggt.
Die marginale Verzögerung beim Aufbau der Verbindungen sollte aus Sicht des Nutzers nicht zu spüren sein und spätestens dann vertretbar sein, wenn solch ein Problem-Fall eintritt.

Um nun zu diesem Verhalten zu wechseln müssen lediglich zwei kleine Änderungen in der conf/authn/ldap-authn-config.xml getätigt werden.
Wir entfernen hier das Wort „Pooled“ aus den class-Bezeichnungen und den connectionFactory-Referenzen und schon wird statt der PooledConnectionFactory die DefaultConnectionFactory benutzt.

conf/authn/ldap-authn-config.xml
<!-- ... -->
 
<!-- Authentication handler -->
    <bean id="authHandler" class="org.ldaptive.auth.BindAuthenticationHandler" p:connectionFactory-ref="bindConnectionFactory" />
<!--
    <bean id="authHandler" class="org.ldaptive.auth.PooledBindAuthenticationHandler" p:connectionFactory-ref="bindPooledConnectionFactory" />
-->
    <bean id="bindPooledConnectionFactory" class="org.ldaptive.pool.PooledConnectionFactory" p:connectionPool-ref="bindConnectionPool" />
    <bean id="bindConnectionPool" class="org.ldaptive.pool.BlockingConnectionPool" parent="connectionPool"
        p:connectionFactory-ref="bindConnectionFactory" p:name="bind-pool" />
    <bean id="bindConnectionFactory" class="org.ldaptive.DefaultConnectionFactory" p:connectionConfig-ref="bindConnectionConfig" />
    <bean id="bindConnectionConfig" parent="connectionConfig" />
 
<!-- ... -->
 
<!-- Bind Search Configuration -->
    <bean name="bindSearchAuthenticator" class="org.ldaptive.auth.Authenticator">
        <constructor-arg index="0" ref="bindSearchDnResolver" />
        <constructor-arg index="1" ref="authHandler" />
    </bean>
    <bean id="bindSearchDnResolver" class="org.ldaptive.auth.SearchDnResolver" p:baseDn="%{idp.authn.LDAP.baseDN}"
        p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}" p:userFilter="%{idp.authn.LDAP.userFilter}"
        p:connectionFactory-ref="bindSearchConnectionFactory" />
<!--
    <bean id="bindSearchDnResolver" class="org.ldaptive.auth.PooledSearchDnResolver" p:baseDn="%{idp.authn.LDAP.baseDN}"
        p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}" p:userFilter="%{idp.authn.LDAP.userFilter}"
        p:connectionFactory-ref="bindSearchPooledConnectionFactory" />
-->
    <bean id="bindSearchPooledConnectionFactory" class="org.ldaptive.pool.PooledConnectionFactory"
        p:connectionPool-ref="bindSearchConnectionPool" />
    <bean id="bindSearchConnectionPool" class="org.ldaptive.pool.BlockingConnectionPool" parent="connectionPool"
        p:connectionFactory-ref="bindSearchConnectionFactory" p:name="search-pool" />
    <bean id="bindSearchConnectionFactory" class="org.ldaptive.DefaultConnectionFactory" p:connectionConfig-ref="bindSearchConnectionConfig" />
    <bean id="bindSearchConnectionConfig" parent="connectionConfig" p:connectionInitializer-ref="bindConnectionInitializer" />
    <bean id="bindConnectionInitializer" class="org.ldaptive.BindConnectionInitializer" p:bindDn="%{idp.authn.LDAP.bindDN}">
        <property name="bindCredential">
            <bean class="org.ldaptive.Credential">
                <constructor-arg value="%{idp.authn.LDAP.bindDNCredential}" />
            </bean>
        </property>
    </bean>
 
<!-- ... -->
  • Zuletzt geändert: vor 2 Jahren