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!
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
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é.