spring-projects / spring-ldap

Spring LDAP
https://spring.io/spring-ldap
Apache License 2.0
339 stars 479 forks source link

Missing data from get all users in 2.3.2 #496

Open kanondev7 opened 5 years ago

kanondev7 commented 5 years ago

We are experiencing an issue that appears to be related to the threading/pooling in versions after 2.0.1. We have 2 ldap sources (one is an ldap provider that holds 5000 users, the other is AD that holds 3000 users). We have a gui that allows the user to "browse" all users -- returning the user name followed by a count of memberOf: John A. Doe - (12). The text is created in the Controller where we loop through all the users returned from our query of each source. Something strange is happening. Intermittently, the ldap source returns all the user names with "(0)" accesses. Less frequently, the results from AD are outright missing blocks of users -- some are there, but not all. I could maybe see that the AD results could be from some sort of timeout, but the ldap results are very strange. Any ideas?

rwinch commented 5 years ago

So to be clear...

It sounds like the issue does not happen in 2.0.0 but does happen in 2.0.1+? I'm not seeing anything in the changelog that jumps out at me https://github.com/spring-projects/spring-ldap/issues?q=is%3Aclosed+milestone%3A2.0.1

What are you pool settings?

Does this only happen with a single user or does it only happen with multiple users leveraging the system?

kanondev7 commented 5 years ago

Does not happen on 2.0.1. Happens on 2.3.2. Haven't tried in between. Single user. I'm not at work, so I will have to get the pool settings...

rwinch commented 5 years ago

Ok. It would be helpful if you can find the first version that breaks.

kanondev7 commented 5 years ago

some version info:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <version.org.springframework>4.3.4.RELEASE</version.org.springframework>
    <version.org.springframework.security>4.1.3.RELEASE</version.org.springframework.security>
    <version.org.springframework.ldap>2.3.2.RELEASE</version.org.springframework.ldap>
  </properties>

ldap/pool config:

<sec:global-method-security pre-post-annotations="enabled"/>
    <context:component-scan base-package="com."/>
    <context:annotation-config/>
    <mvc:annotation-driven/>
    <tx:annotation-driven/>
    ...

    <util:map id="ldapEnv">
        <entry key="com.sun.jndi.ldap.connect.timeout" value="1000"/>
        <entry key="com.sun.jndi.ldap.read.timeout" value="100000"/>
        <entry key="com.sun.jndi.ldap.connect.pool.debug" value="all"/>
        <entry key="java.naming.ldap.attributes.binary" value="objectGUID"/>
    </util:map>
    <bean id="adSearchControlValidation" class="javax.naming.directory.SearchControls">
        <property name="searchScope" value="1"/>
        <property name="countLimit" value="1"/>
        <property name="derefLinkFlag" value="false"/>
        <property name="returningObjFlag" value="false"/>
        <property name="timeLimit" value="1000"/>
    </bean>
    <!-- ============== LDAP config =============== -->
    <ldap:context-source
        id="ldapContextSource"
        url="${ldap.appUrl}"
        base="${ldap.base}"
        username="${ldap.userDn}"
        password="${ldap.password}"
        native-pooling="false">
        <ldap:pooling2
            max-total="40"
            max-total-per-key="20"
            max-idle-per-key="1"
            min-idle-per-key="0"
            test-on-borrow="true"
            test-on-create="true"
            eviction-run-interval-millis="120000"
            tests-per-eviction-run="20"
            min-evictable-time-millis="300000"
            max-wait="3000"
            block-when-exhausted="true"
            jmx-enable="true"
            jmx-name-base="ldap"/>          
    </ldap>
    <!-- ============== LDAP secondary source for system info =============== -->
    <ldap:context-source
        id="ldapContextSource2"
        url="${ldap.appUrl}"
        base="${ldap.netBase}"
        username="${ldap.netUserDn}"
        password="${ldap.netPassword}">
        <ldap:pooling
            max-active="5"
            max-total="8"
            max-idle="1"
            min-idle="0"
            test-on-borrow="true"
            test-on-return="true"
            test-while-idle="true"
            eviction-run-interval-millis="60000"
            tests-per-eviction-run="8"
            min-evictable-time-millis="300000"
            when-exhausted="FAIL"/>         
    </ldap>
    <!-- === NOTE: adContextSource is SSL connection for writing === -->
    <ldap:context-source
        id="adContextSource"
        url="${ad.url}"
        base="${ad.base}"
        username="${ad.userDn}"
        password="${ad.password}"
        referral="follow"
        native-pooling="false">
        <ldap:pooling2
            max-total="20"
            max-total-per-key="10"
            max-idle-per-key="1"
            min-idle-per-key="0"
            test-on-borrow="true"
            test-on-create="true"
            eviction-run-interval-millis="120000"
            tests-per-eviction-run="10"
            min-evictable-time-millis="300000"
            max-wait="2000"
            block-when-exhausted="true"
            validation-query-search-controls-ref="adSearchControlValidation"
            validation-query-base="CN=Users"
            validation-query-filter="objectclass=user"
            jmx-enable="true"
            jmx-name-base="ad"/>            
    </ldap>
    <!-- === NOTE: adGlobalContextSource is global catalog connection for reading enmass === -->
    <ldap:context-source
        id="adGlobalContextSource"
        url="${ad.url.global}"
        base="${ad.base}"
        username="${ad.userDn}"
        password="${ad.password}"
        referral="ignore"
        native-pooling="false"
        base-env-props-ref="ldapEnv">
        <ldap:pooling2
            max-total="20"
            max-total-per-key="10"
            max-idle-per-key="1"
            min-idle-per-key="0"
            test-on-borrow="true"
            test-on-create="true"
            eviction-run-interval-millis="120000"
            tests-per-eviction-run="10"
            min-evictable-time-millis="300000"
            max-wait="2000"
            block-when-exhausted="true"
            validation-query-search-controls-ref="adSearchControlValidation"
            validation-query-base="CN=Users"
            validation-query-filter="objectclass=user"
            jmx-enable="true"
            jmx-name-base="adGlobal"/>          
    </ldap>
    <!-- ============== LDAP templates =============== -->
    <ldap:ldap-template id="ldapTemplate" context-source-ref="ldapContextSource"/>
    <ldap:ldap-template id="netscapeTemplate" context-source-ref="ldapContextSource2"/>
    <ldap:ldap-template id="adLdapTemplate" context-source-ref="adContextSource" ignore-partial-result="true"/> 
    <ldap:ldap-template id="adGlobalTemplate" context-source-ref="adGlobalContextSource"/>
kanondev7 commented 5 years ago

I will check some other versions and get back to you. Thanks for responding!!! :)

rwinch commented 5 years ago

Thanks for the additional information.

Looking forward to the updates on finding out the first version that is impacted.

PS: Rather than using a single ` You can use fenced code blocks for formatting code. For example:

```java
System.out.println("hi");
System.out.println("there");
```

will render as

System.out.println("hi");
System.out.println("there");
kanondev7 commented 5 years ago

Version 2.2.0 does not appear to have the problem. I haven't had a chance to check other versions yet.

kanondev7 commented 5 years ago

It looks like the problem first appears in 2.3.1 -- which is unfortunately the version I need to make writing to active directory easier.

rwinch commented 5 years ago

Thanks. This is strange because I do not see any changes introduced into Spring LDAP 2.3.1 that would cause this issue. Any chance you can try to put together a sample?

kanondev7 commented 5 years ago

I've been thinking you might ask for that. I'll look into it.