HADOOP-12897. KerberosAuthenticator.authenticate to include URL on IO failures. 
Contributed by Ajay Kumar.


Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/b0d3c877
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/b0d3c877
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/b0d3c877

Branch: refs/heads/HDFS-12996
Commit: b0d3c877e30312820124cac2eff737fddac9e484
Parents: 324e5a7
Author: Arpit Agarwal <a...@apache.org>
Authored: Tue Feb 20 18:18:58 2018 -0800
Committer: Arpit Agarwal <a...@apache.org>
Committed: Tue Feb 20 18:18:58 2018 -0800

----------------------------------------------------------------------
 .../client/KerberosAuthenticator.java           | 80 +++++++++++++-------
 .../client/TestKerberosAuthenticator.java       | 29 +++++++
 .../hadoop/http/TestHttpServerWithSpengo.java   |  5 +-
 .../org/apache/hadoop/log/TestLogLevel.java     | 18 ++++-
 .../delegation/web/TestWebDelegationToken.java  |  4 +-
 5 files changed, 101 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/b0d3c877/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/KerberosAuthenticator.java
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/KerberosAuthenticator.java
 
b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/KerberosAuthenticator.java
index 942d13c..64d4330 100644
--- 
a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/KerberosAuthenticator.java
+++ 
b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/KerberosAuthenticator.java
@@ -13,6 +13,8 @@
  */
 package org.apache.hadoop.security.authentication.client;
 
+import com.google.common.annotations.VisibleForTesting;
+import java.lang.reflect.Constructor;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.hadoop.security.authentication.server.HttpConstants;
 import org.apache.hadoop.security.authentication.util.AuthToken;
@@ -177,41 +179,65 @@ public class KerberosAuthenticator implements 
Authenticator {
    */
   @Override
   public void authenticate(URL url, AuthenticatedURL.Token token)
-    throws IOException, AuthenticationException {
+      throws IOException, AuthenticationException {
     if (!token.isSet()) {
       this.url = url;
       base64 = new Base64(0);
-      HttpURLConnection conn = token.openConnection(url, connConfigurator);
-      conn.setRequestMethod(AUTH_HTTP_METHOD);
-      conn.connect();
-      
-      boolean needFallback = false;
-      if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
-        LOG.debug("JDK performed authentication on our behalf.");
-        // If the JDK already did the SPNEGO back-and-forth for
-        // us, just pull out the token.
-        AuthenticatedURL.extractToken(conn, token);
-        if (isTokenKerberos(token)) {
-          return;
+      try {
+        HttpURLConnection conn = token.openConnection(url, connConfigurator);
+        conn.setRequestMethod(AUTH_HTTP_METHOD);
+        conn.connect();
+
+        boolean needFallback = false;
+        if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
+          LOG.debug("JDK performed authentication on our behalf.");
+          // If the JDK already did the SPNEGO back-and-forth for
+          // us, just pull out the token.
+          AuthenticatedURL.extractToken(conn, token);
+          if (isTokenKerberos(token)) {
+            return;
+          }
+          needFallback = true;
         }
-        needFallback = true;
-      }
-      if (!needFallback && isNegotiate(conn)) {
-        LOG.debug("Performing our own SPNEGO sequence.");
-        doSpnegoSequence(token);
-      } else {
-        LOG.debug("Using fallback authenticator sequence.");
-        Authenticator auth = getFallBackAuthenticator();
-        // Make sure that the fall back authenticator have the same
-        // ConnectionConfigurator, since the method might be overridden.
-        // Otherwise the fall back authenticator might not have the information
-        // to make the connection (e.g., SSL certificates)
-        auth.setConnectionConfigurator(connConfigurator);
-        auth.authenticate(url, token);
+        if (!needFallback && isNegotiate(conn)) {
+          LOG.debug("Performing our own SPNEGO sequence.");
+          doSpnegoSequence(token);
+        } else {
+          LOG.debug("Using fallback authenticator sequence.");
+          Authenticator auth = getFallBackAuthenticator();
+          // Make sure that the fall back authenticator have the same
+          // ConnectionConfigurator, since the method might be overridden.
+          // Otherwise the fall back authenticator might not have the
+          // information to make the connection (e.g., SSL certificates)
+          auth.setConnectionConfigurator(connConfigurator);
+          auth.authenticate(url, token);
+        }
+      } catch (IOException ex){
+        throw wrapExceptionWithMessage(ex,
+            "Error while authenticating with endpoint: " + url);
+      } catch (AuthenticationException ex){
+        throw wrapExceptionWithMessage(ex,
+            "Error while authenticating with endpoint: " + url);
       }
     }
   }
 
+  @VisibleForTesting
+   static <T extends Exception> T wrapExceptionWithMessage(
+      T exception, String msg) {
+    Class<? extends Throwable> exceptionClass = exception.getClass();
+    try {
+      Constructor<? extends Throwable> ctor = exceptionClass
+          .getConstructor(String.class);
+      Throwable t = ctor.newInstance(msg);
+      return (T) (t.initCause(exception));
+    } catch (Throwable e) {
+      LOG.debug("Unable to wrap exception of type {}, it has "
+          + "no (String) constructor.", exceptionClass, e);
+      return exception;
+    }
+  }
+
   /**
    * If the specified URL does not support SPNEGO authentication, a fallback 
{@link Authenticator} will be used.
    * <p>

http://git-wip-us.apache.org/repos/asf/hadoop/blob/b0d3c877/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestKerberosAuthenticator.java
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestKerberosAuthenticator.java
 
b/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestKerberosAuthenticator.java
index 7db53ba..4aabb34 100644
--- 
a/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestKerberosAuthenticator.java
+++ 
b/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestKerberosAuthenticator.java
@@ -20,6 +20,9 @@ import static 
org.apache.hadoop.security.authentication.server.KerberosAuthentic
 import static 
org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler.KEYTAB;
 import static 
org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler.NAME_RULES;
 
+import java.io.IOException;
+import java.nio.charset.CharacterCodingException;
+import javax.security.sasl.AuthenticationException;
 import org.apache.hadoop.minikdc.KerberosSecurityTestcase;
 import org.apache.hadoop.security.authentication.KerberosTestUtils;
 import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
@@ -218,4 +221,30 @@ public class TestKerberosAuthenticator extends 
KerberosSecurityTestcase {
     });
   }
 
+  @Test(timeout = 60000)
+  public void testWrapExceptionWithMessage() {
+    IOException ex;
+    ex = new IOException("Induced exception");
+    ex = KerberosAuthenticator.wrapExceptionWithMessage(ex, "Error while "
+        + "authenticating with endpoint: localhost");
+    Assert.assertEquals("Induced exception", ex.getCause().getMessage());
+    Assert.assertEquals("Error while authenticating with endpoint: localhost",
+        ex.getMessage());
+
+    ex = new AuthenticationException("Auth exception");
+    ex = KerberosAuthenticator.wrapExceptionWithMessage(ex, "Error while "
+        + "authenticating with endpoint: localhost");
+    Assert.assertEquals("Auth exception", ex.getCause().getMessage());
+    Assert.assertEquals("Error while authenticating with endpoint: localhost",
+        ex.getMessage());
+
+    // Test for Exception with  no (String) constructor
+    // redirect the LOG to and check log message
+    ex = new CharacterCodingException();
+    Exception ex2 = KerberosAuthenticator.wrapExceptionWithMessage(ex,
+        "Error while authenticating with endpoint: localhost");
+    Assert.assertTrue(ex instanceof CharacterCodingException);
+    Assert.assertTrue(ex.equals(ex2));
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/b0d3c877/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServerWithSpengo.java
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServerWithSpengo.java
 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServerWithSpengo.java
index 8f5dd04..e1d7302 100644
--- 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServerWithSpengo.java
+++ 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServerWithSpengo.java
@@ -383,8 +383,9 @@ public class TestHttpServerWithSpengo {
           Assert.fail("should fail with no credentials");
         } catch (AuthenticationException ae) {
           Assert.assertNotNull(ae.getCause());
-          Assert.assertEquals(GSSException.class, ae.getCause().getClass());
-          GSSException gsse = (GSSException)ae.getCause();
+          Assert.assertEquals(GSSException.class,
+              ae.getCause().getCause().getClass());
+          GSSException gsse = (GSSException)ae.getCause().getCause();
           Assert.assertEquals(GSSException.NO_CRED, gsse.getMajor());
         } catch (Throwable t) {
           Assert.fail("Unexpected exception" + t);

http://git-wip-us.apache.org/repos/asf/hadoop/blob/b0d3c877/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/log/TestLogLevel.java
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/log/TestLogLevel.java
 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/log/TestLogLevel.java
index 30bf726..16b4071 100644
--- 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/log/TestLogLevel.java
+++ 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/log/TestLogLevel.java
@@ -356,7 +356,10 @@ public class TestLogLevel extends KerberosSecurityTestcase 
{
       fail("A HTTPS Client should not have succeeded in connecting to a " +
           "HTTP server");
     } catch (SSLException e) {
-      GenericTestUtils.assertExceptionContains("Unrecognized SSL message", e);
+      GenericTestUtils.assertExceptionContains("Error while authenticating "
+          + "with endpoint", e);
+      GenericTestUtils.assertExceptionContains("Unrecognized SSL message", e
+          .getCause());
     }
   }
 
@@ -374,7 +377,10 @@ public class TestLogLevel extends KerberosSecurityTestcase 
{
       fail("A HTTPS Client should not have succeeded in connecting to a " +
           "HTTP server");
     } catch (SSLException e) {
-      GenericTestUtils.assertExceptionContains("Unrecognized SSL message", e);
+      GenericTestUtils.assertExceptionContains("Error while authenticating "
+          + "with endpoint", e);
+      GenericTestUtils.assertExceptionContains("Unrecognized SSL message", e
+          .getCause());
     }
   }
 
@@ -393,8 +399,10 @@ public class TestLogLevel extends KerberosSecurityTestcase 
{
       fail("A HTTP Client should not have succeeded in connecting to a " +
           "HTTPS server");
     } catch (SocketException e) {
+      GenericTestUtils.assertExceptionContains("Error while authenticating "
+          + "with endpoint", e);
       GenericTestUtils.assertExceptionContains(
-          "Unexpected end of file from server", e);
+          "Unexpected end of file from server", e.getCause());
     }
   }
 
@@ -413,8 +421,10 @@ public class TestLogLevel extends KerberosSecurityTestcase 
{
       fail("A HTTP Client should not have succeeded in connecting to a " +
           "HTTPS server");
     }  catch (SocketException e) {
+      GenericTestUtils.assertExceptionContains("Error while authenticating "
+          + "with endpoint", e);
       GenericTestUtils.assertExceptionContains(
-          "Unexpected end of file from server", e);
+          "Unexpected end of file from server", e.getCause());
     }
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/b0d3c877/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/web/TestWebDelegationToken.java
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/web/TestWebDelegationToken.java
 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/web/TestWebDelegationToken.java
index c564b97..1fcc6fa 100644
--- 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/web/TestWebDelegationToken.java
+++ 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/web/TestWebDelegationToken.java
@@ -364,7 +364,7 @@ public class TestWebDelegationToken {
         aUrl.getDelegationToken(nonAuthURL, token, FOO_USER);
         Assert.fail();
       } catch (Exception ex) {
-        Assert.assertTrue(ex.getMessage().contains("401"));
+        Assert.assertTrue(ex.getCause().getMessage().contains("401"));
       }
 
       aUrl.getDelegationToken(authURL, token, FOO_USER);
@@ -776,7 +776,7 @@ public class TestWebDelegationToken {
         aUrl.getDelegationToken(url, token, FOO_USER, doAsUser);
         Assert.fail();
       } catch (AuthenticationException ex) {
-        Assert.assertTrue(ex.getMessage().contains("GSSException"));
+        Assert.assertTrue(ex.getCause().getMessage().contains("GSSException"));
       }
 
       doAsKerberosUser("client", keytabFile.getAbsolutePath(),


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org
For additional commands, e-mail: common-commits-h...@hadoop.apache.org

Reply via email to