ソースを参照

AMBARI-3251. When Bind DN credentials are incorrect - we should log it

Lisnichenko Dmitro 12 年 前
コミット
59b24e5123

+ 24 - 9
ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLdapAuthenticationProvider.java

@@ -37,7 +37,7 @@ import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
  * Provides LDAP user authorization logic for Ambari Server
  */
 public class AmbariLdapAuthenticationProvider implements AuthenticationProvider {
-  private static final Logger log = LoggerFactory.getLogger(AmbariLdapAuthenticationProvider.class);
+  Logger LOG = LoggerFactory.getLogger(AmbariLdapAuthenticationProvider.class);
 
   Configuration configuration;
 
@@ -56,9 +56,24 @@ public class AmbariLdapAuthenticationProvider implements AuthenticationProvider
   public Authentication authenticate(Authentication authentication) throws AuthenticationException {
 
     if (isLdapEnabled()) {
-
-      return loadLdapAuthenticationProvider().authenticate(authentication);
-
+      try {
+        return loadLdapAuthenticationProvider().authenticate(authentication);
+      } catch (AuthenticationException e) {
+        LOG.debug("Got exception during LDAP authentification attempt", e);
+        // Try to help in troubleshooting
+        Throwable cause = e.getCause();
+        if (cause != null) {
+          // Below we check the cause of an AuthenticationException . If it is
+          // caused by another AuthenticationException, than probably
+          // the problem is with LDAP ManagerDN/password
+          if ((cause != e) && (cause instanceof
+                  org.springframework.ldap.AuthenticationException)) {
+            LOG.warn("Looks like LDAP manager credentials (that are used for " +
+                    "connecting to LDAP server) are invalid.", e);
+          }
+        }
+        throw e;
+      }
     } else {
       return null;
     }
@@ -74,9 +89,9 @@ public class AmbariLdapAuthenticationProvider implements AuthenticationProvider
    * Reloads LDAP Context Source and depending objects if properties were changed
    * @return corresponding LDAP authentication provider
    */
-  private LdapAuthenticationProvider loadLdapAuthenticationProvider() {
+  LdapAuthenticationProvider loadLdapAuthenticationProvider() {
     if (reloadLdapServerProperties()) {
-      log.info("LDAP Properties changed - rebuilding Context");
+      LOG.info("LDAP Properties changed - rebuilding Context");
       LdapContextSource springSecurityContextSource = new LdapContextSource();
       List<String> ldapUrls = ldapServerProperties.get().getLdapUrls();
       springSecurityContextSource.setUrls(ldapUrls.toArray(new String[ldapUrls.size()]));
@@ -90,7 +105,7 @@ public class AmbariLdapAuthenticationProvider implements AuthenticationProvider
       try {
         springSecurityContextSource.afterPropertiesSet();
       } catch (Exception e) {
-        log.error("LDAP Context Source not loaded ", e);
+        LOG.error("LDAP Context Source not loaded ", e);
         throw new UsernameNotFoundException("LDAP Context Source not loaded", e);
       }
 
@@ -116,7 +131,7 @@ public class AmbariLdapAuthenticationProvider implements AuthenticationProvider
    * Check if LDAP authentication is enabled in server properties
    * @return true if enabled
    */
-  private boolean isLdapEnabled() {
+  boolean isLdapEnabled() {
     return configuration.getClientSecurityType() == ClientSecurityType.LDAP;
   }
 
@@ -128,7 +143,7 @@ public class AmbariLdapAuthenticationProvider implements AuthenticationProvider
   private boolean reloadLdapServerProperties() {
     LdapServerProperties properties = configuration.getLdapServerProperties();
     if (!properties.equals(ldapServerProperties.get())) {
-      log.info("Reloading properties");
+      LOG.info("Reloading properties");
       ldapServerProperties.set(properties);
       return true;
     }

+ 75 - 3
ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLdapAuthenticationProviderTest.java

@@ -22,27 +22,29 @@ import junit.framework.Assert;
 import com.google.inject.Guice;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
-import com.google.inject.persist.jpa.JpaPersistModule;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
-import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
 import org.apache.ambari.server.orm.dao.RoleDAO;
 import org.apache.ambari.server.orm.dao.UserDAO;
 import org.apache.ambari.server.orm.entities.RoleEntity;
 import org.apache.ambari.server.orm.entities.UserEntity;
 import org.apache.ambari.server.security.ClientSecurityType;
+import org.easymock.EasyMockSupport;
+import org.easymock.IAnswer;
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.slf4j.Logger;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.ldap.server.ApacheDSContainer;
+import static org.easymock.EasyMock.*;
 
 import static org.junit.Assert.*;
 
-public class AmbariLdapAuthenticationProviderTest{
+public class AmbariLdapAuthenticationProviderTest extends EasyMockSupport {
 
   private static ApacheDSContainer apacheDSContainer;
   private static Injector injector;
@@ -78,6 +80,76 @@ public class AmbariLdapAuthenticationProviderTest{
     authenticationProvider.authenticate(authentication);
   }
 
+
+  @Test
+  public void testGoodManagerCredentials() throws Exception {
+    AmbariLdapAuthoritiesPopulator authoritiesPopulator = createMock(AmbariLdapAuthoritiesPopulator.class);
+    AmbariLdapAuthenticationProvider provider = createMockBuilder(AmbariLdapAuthenticationProvider.class)
+            .addMockedMethod("loadLdapAuthenticationProvider")
+            .addMockedMethod("isLdapEnabled")
+            .withConstructor(configuration, authoritiesPopulator).createMock();
+    // Create the last thrown exception
+    org.springframework.security.core.AuthenticationException exception =
+            createNiceMock(org.springframework.security.core.AuthenticationException.class);
+    expect(exception.getCause()).andReturn(exception).atLeastOnce();
+
+    expect(provider.isLdapEnabled()).andReturn(true);
+    expect(provider.loadLdapAuthenticationProvider()).andThrow(exception);
+    // Logging call
+    Logger log = createNiceMock(Logger.class);
+    provider.LOG = log;
+    log.warn(find("LDAP manager credentials"), (Throwable) anyObject());
+    expectLastCall().andAnswer(new IAnswer<Object>() {
+      @Override
+      public Object answer() throws Throwable {
+        fail("Should not print warning when LDAP manager credentials are not wrong");
+        return null;
+      }
+    }).anyTimes();
+    replayAll();
+    Authentication authentication = new UsernamePasswordAuthenticationToken("notFound", "wrong");
+    try {
+      provider.authenticate(authentication);
+      fail("Should throw exception");
+    } catch(org.springframework.security.core.AuthenticationException e) {
+      // expected
+    }
+    verifyAll();
+  }
+
+  @Test
+  public void testBadManagerCredentials() throws Exception {
+    AmbariLdapAuthoritiesPopulator authoritiesPopulator = createMock(AmbariLdapAuthoritiesPopulator.class);
+    AmbariLdapAuthenticationProvider provider = createMockBuilder(AmbariLdapAuthenticationProvider.class)
+            .addMockedMethod("loadLdapAuthenticationProvider")
+            .addMockedMethod("isLdapEnabled")
+            .withConstructor(configuration, authoritiesPopulator).createMock();
+    // Create the cause
+    org.springframework.ldap.AuthenticationException cause =
+            createNiceMock(org.springframework.ldap.AuthenticationException.class);
+    // Create the last thrown exception
+    org.springframework.security.core.AuthenticationException exception =
+            createNiceMock(org.springframework.security.core.AuthenticationException.class);
+    expect(exception.getCause()).andReturn(cause).atLeastOnce();
+
+    expect(provider.isLdapEnabled()).andReturn(true);
+    expect(provider.loadLdapAuthenticationProvider()).andThrow(exception);
+    // Logging call
+    Logger log = createNiceMock(Logger.class);
+    provider.LOG = log;
+    log.warn(find("LDAP manager credentials"), (Throwable) anyObject());
+    expectLastCall().atLeastOnce();
+    replayAll();
+    Authentication authentication = new UsernamePasswordAuthenticationToken("notFound", "wrong");
+    try {
+      provider.authenticate(authentication);
+      fail("Should throw exception");
+    } catch(org.springframework.security.core.AuthenticationException e) {
+      // expected
+    }
+    verifyAll();
+  }
+
   @Test
   public void testAuthenticate() throws Exception {
     assertNull("User alread exists in DB", userDAO.findLdapUserByName("allowedUser"));