Spring Boot Actuator - LDAP Health Endpoint Throwing NPE

15,781

Solution 1

This is a spring-ldap bug that has a fix committed, but it doesn't appear to be merged into the main spring-ldap branch yet.

However, I have found that adding this property in application.properties fixes the issue:

management.health.ldap.enabled=false

Solution 2

Another solution is to enter credentials into the LDAP Spring properties so they are picked up by the LDAPAutoConfiguration:

[email protected]
spring.ldap.password=secret
spring.ldap.urls=ldap://mydomain.com:389

This way, you can still use the health check.

Share:
15,781

Related videos on Youtube

justbaum30
Author by

justbaum30

Updated on June 04, 2022

Comments

  • justbaum30
    justbaum30 almost 2 years

    In our Spring Boot app we have are using spring-security-ldap to authenticate users that can access our app. We don't see any issues functionally with authentication, however when we hit the /authenticator/health URL, we get the following status for the ldap:

    "ldap": {
        "status": "DOWN",
        "error": "java.lang.NullPointerException: null"
    }
    

    Tracking down this null pointer exception, we get this trace when trying to access the env.put(Context.SECURITY_PRINCIPAL, userDn);:

    java.lang.NullPointerException: null
        at java.util.Hashtable.put(Unknown Source) ~[na:1.8.0_111]
        at org.springframework.ldap.core.support.SimpleDirContextAuthenticationStrategy.setupEnvironment(SimpleDirContextAuthenticationStrategy.java:42) ~[spring-ldap-core-2.3.1.RELEASE.jar:2.3.1.RELEASE]
        at org.springframework.ldap.core.support.AbstractContextSource.setupAuthenticatedEnvironment(AbstractContextSource.java:194) ~[spring-ldap-core-2.3.1.RELEASE.jar:2.3.1.RELEASE]
        at org.springframework.ldap.core.support.AbstractContextSource.getAuthenticatedEnv(AbstractContextSource.java:582) ~[spring-ldap-core-2.3.1.RELEASE.jar:2.3.1.RELEASE]
        at org.springframework.ldap.core.support.AbstractContextSource.doGetContext(AbstractContextSource.java:134) ~[spring-ldap-core-2.3.1.RELEASE.jar:2.3.1.RELEASE]
        at org.springframework.ldap.core.support.AbstractContextSource.getReadOnlyContext(AbstractContextSource.java:158) ~[spring-ldap-core-2.3.1.RELEASE.jar:2.3.1.RELEASE]
        at org.springframework.ldap.core.LdapTemplate.executeReadOnly(LdapTemplate.java:802) ~[spring-ldap-core-2.3.1.RELEASE.jar:2.3.1.RELEASE]
        at org.springframework.boot.actuate.health.LdapHealthIndicator.doHealthCheck(LdapHealthIndicator.java:46) ~[spring-boot-actuator-1.5.4.RELEASE.jar:1.5.4.RELEASE]
        at org.springframework.boot.actuate.health.AbstractHealthIndicator.health(AbstractHealthIndicator.java:43) ~[spring-boot-actuator-1.5.4.RELEASE.jar:1.5.4.RELEASE]
        at org.springframework.boot.actuate.health.CompositeHealthIndicator.health(CompositeHealthIndicator.java:68) [spring-boot-actuator-1.5.4.RELEASE.jar:1.5.4.RELEASE]
        at org.springframework.boot.actuate.endpoint.HealthEndpoint.invoke(HealthEndpoint.java:81) [spring-boot-actuator-1.5.4.RELEASE.jar:1.5.4.RELEASE]
        at org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.getHealth(HealthMvcEndpoint.java:171) [spring-boot-actuator-1.5.4.RELEASE.jar:1.5.4.RELEASE]
        at org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(HealthMvcEndpoint.java:145) [spring-boot-actuator-1.5.4.RELEASE.jar:1.5.4.RELEASE]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_111]
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_111]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_111]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_111]
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) [spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) [spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) [spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) [spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) [spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) [spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) [spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) [spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) [spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) [tomcat-embed-core-8.5.15.jar:8.5.15]
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.15.jar:8.5.15]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.15.jar:8.5.15]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.15.jar:8.5.15]
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.15.jar:8.5.15]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.15.jar:8.5.15]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.15.jar:8.5.15]
    ...
    

    Finally, here is what our security configuration looks like:

    @Configuration
    @EnableWebSecurity
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
        @Value("${security.ldap.url}")
        private String ldapUrl;
        @Value("${security.ldap.user-search-base}")
        private String ldapUserSearchBase;
        @Value("${security.ldap.group-search-base}")
        private String ldapGroupSearchBase;
        @Value("${security.ldap.group-role-attribute}")
        private String ldapGroupRoleAttribute;
        @Value("${security.ldap.authorized-role}")
        private String ldapAuthorizedRole;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // secure all core/data rest endpoints with basic auth
            http.authorizeRequests()
                    .antMatchers("/core/data/unauthenticated/**").permitAll()
                    .antMatchers("/core/data/**").hasRole(ldapAuthorizedRole)
                    .and().httpBasic()
                    .and().csrf().disable();
    
            // do not create sessions for security
            http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        }
    
        @Autowired
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            // use ldap as the authentication provider
            auth.ldapAuthentication()
                    .userSearchBase(ldapUserSearchBase)
                    .userSearchFilter("(uid={0})")
                    .groupSearchBase(ldapGroupSearchBase)
                    .groupSearchFilter("uniqueMember={0}")
                    .groupRoleAttribute(ldapGroupRoleAttribute)
                    .contextSource()
                    .url(ldapUrl);
        }
    
    }
    

    Now we do get a message in the console saying 2017-10-24 12:37:28.867 INFO 12788 --- [ restartedMain] o.s.l.c.support.AbstractContextSource : Property 'userDn' not set - anonymous context will be used for read-write operations, but this is our expectation and we're good with that. It seems the health endpoints isn't respecting this. I can't tell if this is a bug with our code or if it's an issue with the autoconfiguration for Spring Boot.

    I'm a bit unfamiliar with how exactly the Actuator endpoints work, so apologize if this is somewhat obvious. Thanks!

  • belgoros
    belgoros almost 5 years
    I'm using 2.3.2-release version of spring-ldap-core and adding management.health.ldap.enabled=false to application.yml did fixed the problem :).
  • pixel
    pixel about 2 years
    It does not fix the issue, it just removes LDAP check when hitting health endpoint
  • pixel
    pixel about 2 years
    This should be marked as an answer. This resolves the issue and /health actuator endpoint will report status of Ldap. The above accepted answer is incorrect as it does not solve connectivity issue with Ldap but just removes check for Ldap in the /health endpoint
  • pixel
    pixel about 2 years
    This does not fix the issue. It just removes LDAP check when hitting /actuator/health endpoint resulting in Ldap not being checked at all.