Spring Bootアプリでは、_spring-security-ldap
_を使用して、アプリにアクセスできるユーザーを認証しています。認証に関する機能的な問題はありませんが、_/authenticator/health
_ URLにアクセスすると、LDAPの次のステータスが表示されます。
_"ldap": {
"status": "DOWN",
"error": "Java.lang.NullPointerException: null"
}
_
このnullポインター例外を追跡すると、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]
...
_
最後に、セキュリティ構成は次のようになります。
_@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);
}
}
_
これで、コンソールに_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
_というメッセージが表示されますが、これは私たちの期待であり、問題はありません。健康エンドポイントはこれを尊重していないようです。これがコードのバグなのか、Spring Bootの自動構成の問題なのかはわかりません。
Actuatorエンドポイントが正確にどのように機能するのか、私は少し不慣れです。ありがとう!
これは spring-ldapバグ 修正がコミットされていますが、メインのspring-ldap
ブランチにまだマージされていないようです。
ただし、このプロパティをapplication.properties
に追加すると問題が解決することがわかりました。
management.health.ldap.enabled=false
別の解決策は、LDAPSpringプロパティに資格情報を入力して、LDAPAutoConfigurationによって取得されるようにすることです。
[email protected]
spring.ldap.password=secret
spring.ldap.urls=ldap://mydomain.com:389
この方法でも、ヘルスチェックを使用できます。