Return-Path: X-Original-To: apmail-hadoop-common-commits-archive@www.apache.org Delivered-To: apmail-hadoop-common-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 0DDA2171D0 for ; Thu, 6 Nov 2014 02:18:24 +0000 (UTC) Received: (qmail 80966 invoked by uid 500); 6 Nov 2014 02:18:23 -0000 Delivered-To: apmail-hadoop-common-commits-archive@hadoop.apache.org Received: (qmail 80898 invoked by uid 500); 6 Nov 2014 02:18:23 -0000 Mailing-List: contact common-commits-help@hadoop.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: common-dev@hadoop.apache.org Delivered-To: mailing list common-commits@hadoop.apache.org Received: (qmail 80859 invoked by uid 99); 6 Nov 2014 02:18:23 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 06 Nov 2014 02:18:23 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 3D93790AB0B; Thu, 6 Nov 2014 02:18:23 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: atm@apache.org To: common-commits@hadoop.apache.org Date: Thu, 06 Nov 2014 02:18:24 -0000 Message-Id: <6d6fe56efd194d37883c146ac3f9419d@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [2/2] git commit: HADOOP-11187 NameNode - KMS communication fails after a long period of inactivity. Contributed by Arun Suresh. HADOOP-11187 NameNode - KMS communication fails after a long period of inactivity. Contributed by Arun Suresh. Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/ef5af4f8 Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/ef5af4f8 Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/ef5af4f8 Branch: refs/heads/trunk Commit: ef5af4f8de91fbe7891ae3471eb03397e74e1811 Parents: 86eb27b Author: Aaron T. Myers Authored: Wed Nov 5 18:15:12 2014 -0800 Committer: Aaron T. Myers Committed: Wed Nov 5 18:17:49 2014 -0800 ---------------------------------------------------------------------- .../server/AuthenticationFilter.java | 9 ++++++ .../server/AuthenticationHandler.java | 3 ++ .../server/KerberosAuthenticationHandler.java | 2 +- .../server/PseudoAuthenticationHandler.java | 9 ++++-- .../client/TestPseudoAuthenticator.java | 5 +-- .../server/TestAuthenticationFilter.java | 4 ++- .../server/TestPseudoAuthenticationHandler.java | 9 ++---- hadoop-common-project/hadoop-common/CHANGES.txt | 3 ++ .../crypto/key/kms/KMSClientProvider.java | 5 ++- .../hadoop/crypto/key/kms/server/TestKMS.java | 32 ++++++++------------ 10 files changed, 49 insertions(+), 32 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hadoop/blob/ef5af4f8/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java index 58d97ca..0ac352b 100644 --- a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java +++ b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java @@ -17,6 +17,7 @@ import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.security.authentication.client.AuthenticatedURL; import org.apache.hadoop.security.authentication.client.AuthenticationException; +import org.apache.hadoop.security.authentication.client.KerberosAuthenticator; import org.apache.hadoop.security.authentication.util.Signer; import org.apache.hadoop.security.authentication.util.SignerException; import org.apache.hadoop.security.authentication.util.RandomSignerSecretProvider; @@ -36,6 +37,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; + import java.io.IOException; import java.security.Principal; import java.text.SimpleDateFormat; @@ -565,6 +567,13 @@ public class AuthenticationFilter implements Filter { if (!httpResponse.isCommitted()) { createAuthCookie(httpResponse, "", getCookieDomain(), getCookiePath(), 0, isHttps); + // If response code is 401. Then WWW-Authenticate Header should be + // present.. reset to 403 if not found.. + if ((errCode == HttpServletResponse.SC_UNAUTHORIZED) + && (!httpResponse.containsHeader( + KerberosAuthenticator.WWW_AUTHENTICATE))) { + errCode = HttpServletResponse.SC_FORBIDDEN; + } if (authenticationEx == null) { httpResponse.sendError(errCode, "Authentication required"); } else { http://git-wip-us.apache.org/repos/asf/hadoop/blob/ef5af4f8/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationHandler.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationHandler.java b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationHandler.java index 7cafe8b..04984be 100644 --- a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationHandler.java +++ b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationHandler.java @@ -18,6 +18,7 @@ import org.apache.hadoop.security.authentication.client.AuthenticationException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import java.io.IOException; import java.util.Properties; @@ -30,6 +31,8 @@ import java.util.Properties; */ public interface AuthenticationHandler { + public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; + /** * Returns the authentication type of the authentication handler. *

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ef5af4f8/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/KerberosAuthenticationHandler.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/KerberosAuthenticationHandler.java b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/KerberosAuthenticationHandler.java index 9852460..92bc57c 100644 --- a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/KerberosAuthenticationHandler.java +++ b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/KerberosAuthenticationHandler.java @@ -331,7 +331,7 @@ public class KerberosAuthenticationHandler implements AuthenticationHandler { String authorization = request.getHeader(KerberosAuthenticator.AUTHORIZATION); if (authorization == null || !authorization.startsWith(KerberosAuthenticator.NEGOTIATE)) { - response.setHeader(KerberosAuthenticator.WWW_AUTHENTICATE, KerberosAuthenticator.NEGOTIATE); + response.setHeader(WWW_AUTHENTICATE, KerberosAuthenticator.NEGOTIATE); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); if (authorization == null) { LOG.trace("SPNEGO starting"); http://git-wip-us.apache.org/repos/asf/hadoop/blob/ef5af4f8/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/PseudoAuthenticationHandler.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/PseudoAuthenticationHandler.java b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/PseudoAuthenticationHandler.java index 0b329e0..2c7db88 100644 --- a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/PseudoAuthenticationHandler.java +++ b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/PseudoAuthenticationHandler.java @@ -15,13 +15,13 @@ package org.apache.hadoop.security.authentication.server; import org.apache.hadoop.security.authentication.client.AuthenticationException; import org.apache.hadoop.security.authentication.client.PseudoAuthenticator; - import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.NameValuePair; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import java.io.IOException; import java.nio.charset.Charset; import java.util.List; @@ -54,6 +54,9 @@ public class PseudoAuthenticationHandler implements AuthenticationHandler { public static final String ANONYMOUS_ALLOWED = TYPE + ".anonymous.allowed"; private static final Charset UTF8_CHARSET = Charset.forName("UTF-8"); + + private static final String PSEUDO_AUTH = "PseudoAuth"; + private boolean acceptAnonymous; private String type; @@ -181,7 +184,9 @@ public class PseudoAuthenticationHandler implements AuthenticationHandler { if (getAcceptAnonymous()) { token = AuthenticationToken.ANONYMOUS; } else { - throw new AuthenticationException("Anonymous requests are disallowed"); + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + response.setHeader(WWW_AUTHENTICATE, PSEUDO_AUTH); + token = null; } } else { token = new AuthenticationToken(userName, userName, getType()); http://git-wip-us.apache.org/repos/asf/hadoop/blob/ef5af4f8/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestPseudoAuthenticator.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestPseudoAuthenticator.java b/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestPseudoAuthenticator.java index 4a33fa9..3a5764b 100644 --- a/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestPseudoAuthenticator.java +++ b/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/client/TestPseudoAuthenticator.java @@ -63,8 +63,9 @@ public class TestPseudoAuthenticator { URL url = new URL(auth.getBaseURL()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.connect(); - Assert.assertEquals(HttpURLConnection.HTTP_FORBIDDEN, conn.getResponseCode()); - Assert.assertEquals("Anonymous requests are disallowed", conn.getResponseMessage()); + Assert.assertEquals(HttpURLConnection.HTTP_UNAUTHORIZED, conn.getResponseCode()); + Assert.assertTrue(conn.getHeaderFields().containsKey("WWW-Authenticate")); + Assert.assertEquals("Authentication required", conn.getResponseMessage()); } finally { auth.stop(); } http://git-wip-us.apache.org/repos/asf/hadoop/blob/ef5af4f8/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestAuthenticationFilter.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestAuthenticationFilter.java b/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestAuthenticationFilter.java index 3b6b958..c01c182 100644 --- a/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestAuthenticationFilter.java +++ b/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestAuthenticationFilter.java @@ -537,11 +537,11 @@ public class TestAuthenticationFilter { } ).when(chain).doFilter(Mockito.anyObject(), Mockito.anyObject()); + Mockito.when(response.containsHeader("WWW-Authenticate")).thenReturn(true); filter.doFilter(request, response, chain); Mockito.verify(response).sendError( HttpServletResponse.SC_UNAUTHORIZED, "Authentication required"); - Mockito.verify(response).setHeader("WWW-Authenticate", "dummyauth"); } finally { filter.destroy(); } @@ -852,6 +852,7 @@ public class TestAuthenticationFilter { Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie}); HttpServletResponse response = Mockito.mock(HttpServletResponse.class); + Mockito.when(response.containsHeader("WWW-Authenticate")).thenReturn(true); FilterChain chain = Mockito.mock(FilterChain.class); verifyUnauthorized(filter, request, response, chain); @@ -930,6 +931,7 @@ public class TestAuthenticationFilter { Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie}); HttpServletResponse response = Mockito.mock(HttpServletResponse.class); + Mockito.when(response.containsHeader("WWW-Authenticate")).thenReturn(true); FilterChain chain = Mockito.mock(FilterChain.class); verifyUnauthorized(filter, request, response, chain); http://git-wip-us.apache.org/repos/asf/hadoop/blob/ef5af4f8/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestPseudoAuthenticationHandler.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestPseudoAuthenticationHandler.java b/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestPseudoAuthenticationHandler.java index 91c1103..b52915d 100644 --- a/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestPseudoAuthenticationHandler.java +++ b/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestPseudoAuthenticationHandler.java @@ -21,6 +21,7 @@ import org.mockito.Mockito; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import java.util.Properties; public class TestPseudoAuthenticationHandler { @@ -74,12 +75,8 @@ public class TestPseudoAuthenticationHandler { HttpServletRequest request = Mockito.mock(HttpServletRequest.class); HttpServletResponse response = Mockito.mock(HttpServletResponse.class); - handler.authenticate(request, response); - Assert.fail(); - } catch (AuthenticationException ex) { - // Expected - } catch (Exception ex) { - Assert.fail(); + AuthenticationToken token = handler.authenticate(request, response); + Assert.assertNull(token); } finally { handler.destroy(); } http://git-wip-us.apache.org/repos/asf/hadoop/blob/ef5af4f8/hadoop-common-project/hadoop-common/CHANGES.txt ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index 55ef9d3..8587f12 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -412,6 +412,9 @@ Release 2.7.0 - UNRELEASED HADOOP-11272. Allow ZKSignerSecretProvider and ZKDelegationTokenSecretManager to use the same curator client. (Arun Suresh via atm) + HADOOP-11187 NameNode - KMS communication fails after a long period of + inactivity. (Arun Suresh via atm) + Release 2.6.0 - UNRELEASED INCOMPATIBLE CHANGES http://git-wip-us.apache.org/repos/asf/hadoop/blob/ef5af4f8/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/kms/KMSClientProvider.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/kms/KMSClientProvider.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/kms/KMSClientProvider.java index 4c24f58..cb03683 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/kms/KMSClientProvider.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/kms/KMSClientProvider.java @@ -81,6 +81,8 @@ import com.google.common.base.Preconditions; public class KMSClientProvider extends KeyProvider implements CryptoExtension, KeyProviderDelegationTokenExtension.DelegationTokenExtension { + private static final String INVALID_SIGNATURE = "Invalid signature"; + private static final String ANONYMOUS_REQUESTS_DISALLOWED = "Anonymous requests are disallowed"; public static final String TOKEN_KIND = "kms-dt"; @@ -453,7 +455,8 @@ public class KMSClientProvider extends KeyProvider implements CryptoExtension, throw ex; } if ((conn.getResponseCode() == HttpURLConnection.HTTP_FORBIDDEN - && conn.getResponseMessage().equals(ANONYMOUS_REQUESTS_DISALLOWED)) + && (conn.getResponseMessage().equals(ANONYMOUS_REQUESTS_DISALLOWED) || + conn.getResponseMessage().contains(INVALID_SIGNATURE))) || conn.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) { // Ideally, this should happen only when there is an Authentication // failure. Unfortunately, the AuthenticationFilter returns 403 when it http://git-wip-us.apache.org/repos/asf/hadoop/blob/ef5af4f8/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java b/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java index 9e76178..86e6484 100644 --- a/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java +++ b/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java @@ -900,6 +900,7 @@ public class TestKMS { keytab.getAbsolutePath()); conf.set("hadoop.kms.authentication.kerberos.principal", "HTTP/localhost"); conf.set("hadoop.kms.authentication.kerberos.name.rules", "DEFAULT"); + conf.set("hadoop.kms.authentication.token.validity", "1"); for (KMSACLs.Type type : KMSACLs.Type.values()) { conf.set(type.getAclConfigKey(), type.toString()); @@ -930,11 +931,16 @@ public class TestKMS { @Override public Void run() throws Exception { KMSClientProvider kp = new KMSClientProvider(uri, conf); + + kp.createKey("k0", new byte[16], + new KeyProvider.Options(conf)); + // This happens before rollover kp.createKey("k1", new byte[16], new KeyProvider.Options(conf)); - makeAuthTokenStale(kp); + // Atleast 2 rollovers.. so should induce signer Exception + Thread.sleep(3500); kp.createKey("k2", new byte[16], - new KeyProvider.Options(conf)); + new KeyProvider.Options(conf)); return null; } }); @@ -958,15 +964,16 @@ public class TestKMS { KMSClientProvider kp = new KMSClientProvider(uri, conf); kp.createKey("k3", new byte[16], new KeyProvider.Options(conf)); - makeAuthTokenStale(kp); + // Atleast 2 rollovers.. so should induce signer Exception + Thread.sleep(3500); try { kp.createKey("k4", new byte[16], new KeyProvider.Options(conf)); - Assert.fail("Shoud fail since retry count == 0"); + Assert.fail("This should not succeed.."); } catch (IOException e) { Assert.assertTrue( - "HTTP exception must be a 403 : " + e.getMessage(), e - .getMessage().contains("403")); + "HTTP exception must be a 401 : " + e.getMessage(), e + .getMessage().contains("401")); } return null; } @@ -976,19 +983,6 @@ public class TestKMS { }); } - private void makeAuthTokenStale(KMSClientProvider kp) throws Exception { - Field tokF = KMSClientProvider.class.getDeclaredField("authToken"); - tokF.setAccessible(true); - DelegationTokenAuthenticatedURL.Token delToken = - (DelegationTokenAuthenticatedURL.Token) tokF.get(kp); - String oldTokStr = delToken.toString(); - Method setM = - AuthenticatedURL.Token.class.getDeclaredMethod("set", String.class); - setM.setAccessible(true); - String newTokStr = oldTokStr.replaceAll("e=[^&]*", "e=1000"); - setM.invoke(((AuthenticatedURL.Token)delToken), newTokStr); - } - @Test public void testACLs() throws Exception { Configuration conf = new Configuration();