From 2b08a1fc644904a37545107666efc25b3552542d Mon Sep 17 00:00:00 2001 From: Xiaoyu Yao Date: Fri, 6 Oct 2017 10:12:24 -0700 Subject: [PATCH] HADOOP-14920. KMSClientProvider won't work with KMS delegation token retrieved from non-Java client. Contributed by Xiaoyu Yao. --- .../DelegationTokenAuthenticationHandler.java | 5 +- .../web/DelegationTokenAuthenticator.java | 1 + .../web/DelegationTokenManager.java | 15 +++- ...onTokenAuthenticationHandlerWithMocks.java | 72 +++++++++++++------ 4 files changed, 70 insertions(+), 23 deletions(-) diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationHandler.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationHandler.java index 106c6be8fe2..6ee59f1d175 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationHandler.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationHandler.java @@ -272,8 +272,11 @@ public boolean managementOperation(AuthenticationToken token, } String renewer = ServletUtils.getParameter(request, KerberosDelegationTokenAuthenticator.RENEWER_PARAM); + String service = ServletUtils.getParameter(request, + KerberosDelegationTokenAuthenticator.SERVICE_PARAM); try { - Token dToken = tokenManager.createToken(requestUgi, renewer); + Token dToken = tokenManager.createToken(requestUgi, renewer, + service); map = delegationTokenToJSON(dToken); } catch (IOException ex) { throw new AuthenticationException(ex.toString(), ex); diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticator.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticator.java index 3dba1dbc205..a1c600340e8 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticator.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticator.java @@ -70,6 +70,7 @@ public abstract class DelegationTokenAuthenticator implements Authenticator { public static final String DELEGATION_PARAM = "delegation"; public static final String TOKEN_PARAM = "token"; public static final String RENEWER_PARAM = "renewer"; + public static final String SERVICE_PARAM = "service"; public static final String DELEGATION_TOKEN_JSON = "Token"; public static final String DELEGATION_TOKEN_URL_STRING_JSON = "urlString"; public static final String RENEW_DELEGATION_TOKEN_JSON = "long"; diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenManager.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenManager.java index b1a8d48ad66..fd19b67fb6d 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenManager.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenManager.java @@ -160,7 +160,14 @@ public void destroy() { @SuppressWarnings("unchecked") public Token createToken( UserGroupInformation ugi, String renewer) { - LOG.debug("Creating token with ugi:{}, renewer:{}.", ugi, renewer); + return createToken(ugi, renewer, null); + } + + @SuppressWarnings("unchecked") + public Token createToken( + UserGroupInformation ugi, String renewer, String service) { + LOG.debug("Creating token with ugi:{}, renewer:{}, service:{}.", + ugi, renewer, service !=null ? service : ""); renewer = (renewer == null) ? ugi.getShortUserName() : renewer; String user = ugi.getUserName(); Text owner = new Text(user); @@ -173,7 +180,11 @@ public Token createToken( tokenIdentifier.setOwner(owner); tokenIdentifier.setRenewer(new Text(renewer)); tokenIdentifier.setRealUser(realUser); - return new Token(tokenIdentifier, secretManager); + Token token = new Token(tokenIdentifier, secretManager); + if (service != null) { + token.setService(new Text(service)); + } + return token; } @SuppressWarnings("unchecked") diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/web/TestDelegationTokenAuthenticationHandlerWithMocks.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/web/TestDelegationTokenAuthenticationHandlerWithMocks.java index f62a6ce5a01..9357f48df3c 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/web/TestDelegationTokenAuthenticationHandlerWithMocks.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/web/TestDelegationTokenAuthenticationHandlerWithMocks.java @@ -111,12 +111,21 @@ public void cleanUp() { @Test public void testManagementOperations() throws Exception { - testNonManagementOperation(); - testManagementOperationErrors(); - testGetToken(null, new Text("foo")); - testGetToken("bar", new Text("foo")); - testCancelToken(); - testRenewToken(); + final Text testTokenKind = new Text("foo"); + final String testRenewer = "bar"; + final String testService = "192.168.64.101:8888"; + testNonManagementOperation(); + testManagementOperationErrors(); + testGetToken(null, null, testTokenKind); + testGetToken(testRenewer, null, testTokenKind); + testCancelToken(); + testRenewToken(testRenewer); + + // Management operations against token requested with service parameter + Token testToken = + testGetToken(testRenewer, testService, testTokenKind); + testRenewToken(testToken, testRenewer); + testCancelToken(testToken); } private void testNonManagementOperation() throws Exception { @@ -156,8 +165,8 @@ private void testManagementOperationErrors() throws Exception { Mockito.eq("mock")); } - private void testGetToken(String renewer, Text expectedTokenKind) - throws Exception { + private Token testGetToken(String renewer, + String service, Text expectedTokenKind) throws Exception { DelegationTokenAuthenticator.DelegationTokenOperation op = DelegationTokenAuthenticator.DelegationTokenOperation. GETDELEGATIONTOKEN; @@ -173,10 +182,14 @@ private void testGetToken(String renewer, Text expectedTokenKind) new StringWriter())); Assert.assertFalse(handler.managementOperation(token, request, response)); - Mockito.when(request.getQueryString()). - thenReturn(DelegationTokenAuthenticator.OP_PARAM + "=" + op.toString() + - "&" + DelegationTokenAuthenticator.RENEWER_PARAM + "=" + renewer); - + String queryString = + DelegationTokenAuthenticator.OP_PARAM + "=" + op.toString() + "&" + + DelegationTokenAuthenticator.RENEWER_PARAM + "=" + renewer; + if (service != null) { + queryString += "&" + DelegationTokenAuthenticator.SERVICE_PARAM + "=" + + service; + } + Mockito.when(request.getQueryString()).thenReturn(queryString); Mockito.reset(response); Mockito.reset(token); Mockito.when(token.getUserName()).thenReturn("user"); @@ -208,10 +221,25 @@ private void testGetToken(String renewer, Text expectedTokenKind) dt.decodeFromUrlString(tokenStr); handler.getTokenManager().verifyToken(dt); Assert.assertEquals(expectedTokenKind, dt.getKind()); + if (service != null) { + Assert.assertEquals(service, dt.getService().toString()); + } else { + Assert.assertEquals(0, dt.getService().getLength()); + } + return dt; } @SuppressWarnings("unchecked") private void testCancelToken() throws Exception { + Token token = + (Token) handler.getTokenManager() + .createToken(UserGroupInformation.getCurrentUser(), "foo"); + testCancelToken(token); + } + + @SuppressWarnings("unchecked") + private void testCancelToken(Token token) + throws Exception { DelegationTokenAuthenticator.DelegationTokenOperation op = DelegationTokenAuthenticator.DelegationTokenOperation. CANCELDELEGATIONTOKEN; @@ -228,9 +256,6 @@ private void testCancelToken() throws Exception { Mockito.contains("requires the parameter [token]")); Mockito.reset(response); - Token token = - (Token) handler.getTokenManager().createToken( - UserGroupInformation.getCurrentUser(), "foo"); Mockito.when(request.getQueryString()).thenReturn( DelegationTokenAuthenticator.OP_PARAM + "=" + op.toString() + "&" + DelegationTokenAuthenticator.TOKEN_PARAM + "=" + @@ -249,7 +274,16 @@ private void testCancelToken() throws Exception { } @SuppressWarnings("unchecked") - private void testRenewToken() throws Exception { + private void testRenewToken(String testRenewer) throws Exception { + Token dToken = (Token) + handler.getTokenManager().createToken( + UserGroupInformation.getCurrentUser(), testRenewer); + testRenewToken(dToken, testRenewer); + } + + @SuppressWarnings("unchecked") + private void testRenewToken(Token dToken, + String testRenewer) throws Exception { DelegationTokenAuthenticator.DelegationTokenOperation op = DelegationTokenAuthenticator.DelegationTokenOperation. RENEWDELEGATIONTOKEN; @@ -270,7 +304,7 @@ private void testRenewToken() throws Exception { Mockito.reset(response); AuthenticationToken token = Mockito.mock(AuthenticationToken.class); - Mockito.when(token.getUserName()).thenReturn("user"); + Mockito.when(token.getUserName()).thenReturn(testRenewer); Assert.assertFalse(handler.managementOperation(token, request, response)); Mockito.verify(response).sendError( Mockito.eq(HttpServletResponse.SC_BAD_REQUEST), @@ -280,9 +314,7 @@ private void testRenewToken() throws Exception { StringWriter writer = new StringWriter(); PrintWriter pwriter = new PrintWriter(writer); Mockito.when(response.getWriter()).thenReturn(pwriter); - Token dToken = - (Token) handler.getTokenManager().createToken( - UserGroupInformation.getCurrentUser(), "user"); + Mockito.when(request.getQueryString()). thenReturn(DelegationTokenAuthenticator.OP_PARAM + "=" + op.toString() + "&" + DelegationTokenAuthenticator.TOKEN_PARAM + "=" +