Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
2.4.0
Description
When authenticating using LDAP where the LDAP server is a Centrify LDAP proxy, a NullPointerException is being thrown due to unexpected missing LDAP user object attributes.
10 Nov 2016 08:23:38,789 ERROR [ambari-client-thread-25] AmbariLdapBindAuthenticator:95 - Caught exception java.lang.NullPointerException at org.apache.ambari.server.security.authorization.AmbariLdapBindAuthenticator.authenticate(AmbariLdapBindAuthenticator.java:83) at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.doAuthentication(LdapAuthenticationProvider.java:178) at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:61) at org.apache.ambari.server.security.authorization.AmbariLdapAuthenticationProvider.authenticate(AmbariLdapAuthenticationProvider.java:73) at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156) at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:168) at org.apache.ambari.server.security.authentication.AmbariAuthenticationFilter.doFilter(AmbariAuthenticationFilter.java:88) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.apache.ambari.server.security.authorization.AmbariUserAuthorizationFilter.doFilter(AmbariUserAuthorizationFilter.java:91) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478) at org.apache.ambari.server.api.MethodOverrideFilter.doFilter(MethodOverrideFilter.java:72) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478) at org.apache.ambari.server.api.AmbariPersistFilter.doFilter(AmbariPersistFilter.java:47) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478) at org.apache.ambari.server.security.AbstractSecurityHeaderFilter.doFilter(AbstractSecurityHeaderFilter.java:109) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478) at org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:82) at org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:294) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1478) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:499) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:427) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135) at org.apache.ambari.server.controller.AmbariHandlerList.processHandlers(AmbariHandlerList.java:212) at org.apache.ambari.server.controller.AmbariHandlerList.processHandlers(AmbariHandlerList.java:201) at org.apache.ambari.server.controller.AmbariHandlerList.handle(AmbariHandlerList.java:139) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116) at org.eclipse.jetty.server.Server.handle(Server.java:370) at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494) at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:973) at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1035) at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:641) at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:231) at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:696) at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:53) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543) at java.lang.Thread.run(Thread.java:745)
Cause
The cause for this NPE is related to missing data from the attribute search request made to a Centrify LDAP proxy after a bind has occurred. Since the query filter at this point is "{(objectClass=*}}", the Centrify LDAP proxy does not have enough data to determine what information to return to the caller. However, the filter was something like "{(objectClass=posixAccount}}", it will be able to build a set of attributes to return to the caller since it would determine that the call wants data for a specific profile.
This can be seen by the following tcpdump entry:
LDAPMessage searchRequest(2) "uid=user1,ou=people,ou=dev,dc=apache,dc=org" baseObject
messageID: 2
protocolOp: searchRequest (3)
searchRequest
baseObject: uid=user1,ou=people,ou=dev,dc=apache,dc=org
scope: baseObject (0)
derefAliases: derefAlways (3)
sizeLimit: 0
timeLimit: 0
typesOnly: False
Filter: (objectClass=*)
attributes: 0 items
[Response In: 2]
controls: 1 item
Note the filter line above: Filter: (objectClass=)*
From the Centrify LDAP proxy logs, the following lines can be seen showing that no mapping is avaialbe:
Nov 8 12:13:45 host1 slapd: cdc search start with filterstr: (objectClass=*) Nov 8 12:13:45 host1 slapd: cdc search: objectType = ( is mapped to NONE) Nov 8 12:13:45 host1 slapd: cdc search after translation filter = (objectClass=*)
This search filter is hardcoded in com.sun.jndi.ldap.LdapCtx as seen in http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/com/sun/jndi/ldap/LdapCtx.java#1308.
This code is invoked from the Spring LDAP library after attempting to authenticate using the Spring org.springframework.security.ldap.authentication.BindAuthenticator class.
Solution
To solve this, Ambari should avoid using org.springframework.security.ldap.authentication.BindAuthenticator to authenticate users via LDAP so that more control can be had over when and how user attributes are obtained.
Attachments
Attachments
Issue Links
- links to