Summary

When configuring an embedded ldap server to import an ldif file (e.g., users.ldif), no log message (at not level) is written nor any exception is thrown if the provided file does not exist (e.g., uesrs.ldif):

private void importLdif(InMemoryDirectoryServer directoryServer) {
    if (StringUtils.hasText(this.ldif)) {
        Resource resource = this.context.getResource(this.ldif);
        try {
            if (resource.exists()) {
                try (InputStream inputStream = resource.getInputStream()) {
                    directoryServer.importFromLDIF(false, new LDIFReader(inputStream));
                }
            }
        } catch (Exception ex) {
            throw new IllegalStateException("Unable to load LDIF " + this.ldif, ex);
        }
    }
}

While it is arguably legitimate not to throw an exception in this case and load the ldif file from a default location, logging a message out that warns the user that the configured ldif file was not found could spare some debugging time ;)

Actual Behavior

No log message is provided upon an unsuccessful import of a ldif file.

Expected Behavior

A log message that warns the users that the configured ldif file does not exist

Configuration

<security:ldap-server
        id="local-ldap-server"
        ldif="file:${configpath}/uesrs.ldif"
        port="8389"
        root="dc=springframework,dc=org"
    />

On the file system however, the file is: ${configpath}/users.ldif

Version

5.2.1.RELEASE

Sample

https://github.com/spring-projects/spring-security/blob/master/ldap/src/main/java/org/springframework/security/ldap/server/UnboundIdContainer.java

Comment From: eleftherias

Thanks for the report @ybbabr19.

I agree that the application should not fail silently if the LDIF file is not found. I think it is best to throw an exception. Then it will behave the same as ApacheDSContainer.

Are you interested in submitting a PR to fix this?

Comment From: dratler

If this still an option I would like to contribute to this issue.

Comment From: eleftherias

@dratler thank you, it's yours

Comment From: eleftherias

@dratler Have you had the chance to look into this issue?

Comment From: dratler

Hi @eleftherias , I'm sorry I was over booked. I'm trying yo build ldap server locally . do you have something prepraed ?

Comment From: eleftherias

@dratler We have an LDAP sample in this repository that you can use https://github.com/spring-projects/spring-security/tree/master/samples/javaconfig/ldap You may also find this section of the documentation helpful https://docs.spring.io/spring-security/site/docs/5.3.1.RELEASE/reference/html5/#servlet-authentication-ldap

Comment From: dratler

Hi @eleftherias , I have start wortking on it, I know there is an internal LDAP (LDIF) been used. I would like to use that on is it fine ? Also there are missing dependency within Gradel (@PreDestory annotation etc...). It might take a while...

Comment From: eleftherias

@dratler I hope the guidelines below can help you with the initial setup.

This issue can be demonstrated using the LDAP sample with a few modifications. Firstly, add .contextSource().ldif("classpath:does-not-exist.ldif") to the configuration in SecurityConfig.java. Then, to make the application use "unboundid" mode, replace compile apachedsDependencies with compile "com.unboundid:unboundid-ldapsdk" in the spring-security-samples-javaconfig-ldap.gradle.

If you run the application, you will see that no exception is thrown, even though the file does-not-exist.ldif is not on the classpath. If you were to use "apacheds" mode, then you would see an exception when the file is not found. This is the desired behaviour. If you are curious to try "apacheds" mode, then you can update SecurityConfig.java as mentioned above, but leave the gradle file unchanged (still using the Apache DS dependencies).

The changes required to fix this will be in UnboundIdContainer, specifically the importLdif function. We will need to throw an exception if the supplied resource (resources[0]) does not exist.

Could you please clarify what you mean in your comment above about the missing gradle dependency?

Please don't hesitate to reach out if you need any help or clarifications. Thank you for taking the time to contribute!

Comment From: dratler

Hi @eleftherias , I'm getting package javax.annotation does not exist it's been thrown at the following classes :

  • src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerLdifTests.java src/integration
  • test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManagerModifyPasswordTests.java
  • src/integration-test/java/org/springframework/security/ldap/ApacheDsContainerConfig.java

It affects @PreDestotry annotation. I can add it into Gradle Compile or I'm missing something out?

For example the error

@PreDestroy
     ^
  symbol:   class PreDestroy
  location: class ApacheDsContainerConfig

Comment From: eleftherias

@dratler You do not need to add any additional gradle dependencies. Are you seeing this error in an IDE or command line? Are you able to successfully run ./gradlew clean build?

Comment From: dratler

Hi @eddumelendez , I'm able to run successfully ./gradlew clean build . before I run Gradle clean and build via IDE , I'm using IntelliJ. Now I'm trying to add .contextSource().ldif("classpath:does-not-exist.ldif") to SecurityConfig.java. which one is it? Is there a need to install also SprintFramework ? the path for such file is src/main/resources/org/springframework/security/config/ I have found it at spring-security-config.gradle

thanks you for all the help

Comment From: eleftherias

Is there a need to install also Spring Framework ?

@dratler Spring Framework is already a dependency of Spring Security. There is no additional work needed to use Spring Framework.

I'm able to run successfully ./gradlew clean build . before I run Gradle clean and build via IDE , I'm using IntelliJ.

If you are able to run ./gradlew clean build from the command line, and you cannot compile the project in the IDE, then it means the IDE is not configured correctly. Make sure you are importing it as a Gradle project.

Now I'm trying to add .contextSource().ldif("classpath:does-not-exist.ldif") to SecurityConfig.java. which one is it?

You can add that to the LDAP sample which is found in samples/javaconfig/ldap. This is only to demonstrate the issue.

If you have any further questions, you could open a draft pull request and we can discuss there.

Comment From: dratler

Hi @eleftherias , here is the https://github.com/spring-projects/spring-security/pull/8434 I have opened with the tests for this issue . I would like to here your comments

Comment From: dratler

Hi @eleftherias , I think I have resolved the issue. I have also fixed some test classes.