web-dev-qa-db-fra.com

Spring Boot Actuator - LDAP Health Endpoint Throwing NPE

Dans notre application Spring Boot, nous utilisons spring-security-ldap Pour authentifier les utilisateurs qui peuvent accéder à notre application. Nous ne voyons aucun problème fonctionnel avec l'authentification, cependant lorsque nous atteignons l'URL /authenticator/health, Nous obtenons l'état suivant pour le ldap:

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

En recherchant cette exception de pointeur nul, nous obtenons cette trace lorsque nous essayons d'accéder à la 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]
...

Enfin, voici à quoi ressemble notre configuration de sécurité:

@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);
    }

}

Maintenant, nous recevons un message dans la console disant 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, Mais c'est notre attente et nous sommes bons avec ça. Il semble que les paramètres de santé ne respectent pas cela. Je ne peux pas dire s'il s'agit d'un bogue avec notre code ou s'il s'agit d'un problème avec la configuration automatique pour Spring Boot.

Je ne suis pas familier avec le fonctionnement exact des points de terminaison de l'actionneur, veuillez donc vous excuser si cela est quelque peu évident. Merci!

17
justbaum30

Il s'agit d'un bug spring-ldap qui a un correctif validé, mais il ne semble pas être fusionné dans le _ spring-ldap branche encore.

Cependant, j'ai constaté que l'ajout de cette propriété dans application.properties résout le problème:

management.health.ldap.enabled=false
26
badjr

Une autre solution consiste à entrer les informations d'identification dans les propriétés LDAP Spring afin qu'elles soient récupérées par LDAPAutoConfiguration:

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

De cette façon, vous pouvez toujours utiliser le bilan de santé.

1
Sonata