hadoop-common-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From vino...@apache.org
Subject git commit: HADOOP-11207. Enhanced common DelegationTokenAuthenticationHandler to support proxy-users on Delegation-token management operations. Contributed by Zhijie Shen.
Date Fri, 17 Oct 2014 22:57:50 GMT
Repository: hadoop
Updated Branches:
  refs/heads/branch-2.6 821766529 -> db2bfed83


HADOOP-11207. Enhanced common DelegationTokenAuthenticationHandler to support proxy-users
on Delegation-token management operations. Contributed by Zhijie Shen.

(cherry picked from commit 11375578162d77b78cc3f7a82f2495b1e31a3656)


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

Branch: refs/heads/branch-2.6
Commit: db2bfed8391bf7ff4fec443a691ef53e395c46d8
Parents: 8217665
Author: Vinod Kumar Vavilapalli <vinodkv@apache.org>
Authored: Fri Oct 17 15:56:07 2014 -0700
Committer: Vinod Kumar Vavilapalli <vinodkv@apache.org>
Committed: Fri Oct 17 15:57:39 2014 -0700

----------------------------------------------------------------------
 hadoop-common-project/hadoop-common/CHANGES.txt |  3 +
 .../web/DelegationTokenAuthenticatedURL.java    | 58 +++++++++++++++-
 .../DelegationTokenAuthenticationHandler.java   | 45 +++++++++----
 .../web/DelegationTokenAuthenticator.java       | 71 ++++++++++++++++++--
 .../delegation/web/TestWebDelegationToken.java  | 56 +++++++++++++--
 5 files changed, 205 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/db2bfed8/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 d4262f5..12ae681 100644
--- a/hadoop-common-project/hadoop-common/CHANGES.txt
+++ b/hadoop-common-project/hadoop-common/CHANGES.txt
@@ -232,6 +232,9 @@ Release 2.6.0 - UNRELEASED
     HADOOP-11181. Generalized o.a.h.s.t.d.DelegationTokenManager to handle all
     sub-classes of AbstractDelegationTokenIdentifier. (zjshen)
 
+    HADOOP-11207. Enhanced common DelegationTokenAuthenticationHandler to support
+    proxy-users on Delegation-token management operations. (Zhijie Shen via
+    vinodkv)
 
   OPTIMIZATIONS
 

http://git-wip-us.apache.org/repos/asf/hadoop/blob/db2bfed8/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticatedURL.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticatedURL.java
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticatedURL.java
index 8c7cbdf..7ed0f26 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticatedURL.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticatedURL.java
@@ -333,6 +333,7 @@ public class DelegationTokenAuthenticatedURL extends AuthenticatedURL
{
    * supported.
    * @param token the authentication token being used for the user where the
    * Delegation token will be stored.
+   * @param renewer the renewer user.
    * @return a delegation token.
    * @throws IOException if an IO error occurred.
    * @throws AuthenticationException if an authentication exception occurred.
@@ -340,12 +341,32 @@ public class DelegationTokenAuthenticatedURL extends AuthenticatedURL
{
   public org.apache.hadoop.security.token.Token<AbstractDelegationTokenIdentifier>
       getDelegationToken(URL url, Token token, String renewer)
           throws IOException, AuthenticationException {
+    return getDelegationToken(url, token, renewer, null);
+  }
+
+  /**
+   * Requests a delegation token using the configured <code>Authenticator</code>
+   * for authentication.
+   *
+   * @param url the URL to get the delegation token from. Only HTTP/S URLs are
+   * supported.
+   * @param token the authentication token being used for the user where the
+   * Delegation token will be stored.
+   * @param renewer the renewer user.
+   * @param doAsUser the user to do as, which will be the token owner.
+   * @return a delegation token.
+   * @throws IOException if an IO error occurred.
+   * @throws AuthenticationException if an authentication exception occurred.
+   */
+  public org.apache.hadoop.security.token.Token<AbstractDelegationTokenIdentifier>
+      getDelegationToken(URL url, Token token, String renewer, String doAsUser)
+          throws IOException, AuthenticationException {
     Preconditions.checkNotNull(url, "url");
     Preconditions.checkNotNull(token, "token");
     try {
       token.delegationToken =
           ((KerberosDelegationTokenAuthenticator) getAuthenticator()).
-              getDelegationToken(url, token, renewer);
+              getDelegationToken(url, token, renewer, doAsUser);
       return token.delegationToken;
     } catch (IOException ex) {
       token.delegationToken = null;
@@ -365,13 +386,29 @@ public class DelegationTokenAuthenticatedURL extends AuthenticatedURL
{
    */
   public long renewDelegationToken(URL url, Token token)
       throws IOException, AuthenticationException {
+    return renewDelegationToken(url, token, null);
+  }
+
+  /**
+   * Renews a delegation token from the server end-point using the
+   * configured <code>Authenticator</code> for authentication.
+   *
+   * @param url the URL to renew the delegation token from. Only HTTP/S URLs are
+   * supported.
+   * @param token the authentication token with the Delegation Token to renew.
+   * @param doAsUser the user to do as, which will be the token owner.
+   * @throws IOException if an IO error occurred.
+   * @throws AuthenticationException if an authentication exception occurred.
+   */
+  public long renewDelegationToken(URL url, Token token, String doAsUser)
+      throws IOException, AuthenticationException {
     Preconditions.checkNotNull(url, "url");
     Preconditions.checkNotNull(token, "token");
     Preconditions.checkNotNull(token.delegationToken,
         "No delegation token available");
     try {
       return ((KerberosDelegationTokenAuthenticator) getAuthenticator()).
-          renewDelegationToken(url, token, token.delegationToken);
+          renewDelegationToken(url, token, token.delegationToken, doAsUser);
     } catch (IOException ex) {
       token.delegationToken = null;
       throw ex;
@@ -389,13 +426,28 @@ public class DelegationTokenAuthenticatedURL extends AuthenticatedURL
{
    */
   public void cancelDelegationToken(URL url, Token token)
       throws IOException {
+    cancelDelegationToken(url, token, null);
+  }
+
+  /**
+   * Cancels a delegation token from the server end-point. It does not require
+   * being authenticated by the configured <code>Authenticator</code>.
+   *
+   * @param url the URL to cancel the delegation token from. Only HTTP/S URLs
+   * are supported.
+   * @param token the authentication token with the Delegation Token to cancel.
+   * @param doAsUser the user to do as, which will be the token owner.
+   * @throws IOException if an IO error occurred.
+   */
+  public void cancelDelegationToken(URL url, Token token, String doAsUser)
+      throws IOException {
     Preconditions.checkNotNull(url, "url");
     Preconditions.checkNotNull(token, "token");
     Preconditions.checkNotNull(token.delegationToken,
         "No delegation token available");
     try {
       ((KerberosDelegationTokenAuthenticator) getAuthenticator()).
-          cancelDelegationToken(url, token, token.delegationToken);
+          cancelDelegationToken(url, token, token.delegationToken, doAsUser);
     } finally {
       token.delegationToken = null;
     }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/db2bfed8/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticationHandler.java
----------------------------------------------------------------------
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 8321c5e..c18b5d3 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
@@ -17,7 +17,21 @@
  */
 package org.apache.hadoop.security.token.delegation.web;
 
-import com.google.common.annotations.VisibleForTesting;
+import java.io.IOException;
+import java.io.Writer;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.MediaType;
+
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.classification.InterfaceStability;
 import org.apache.hadoop.conf.Configuration;
@@ -27,25 +41,15 @@ import org.apache.hadoop.security.authentication.client.AuthenticationException;
 import org.apache.hadoop.security.authentication.server.AuthenticationHandler;
 import org.apache.hadoop.security.authentication.server.AuthenticationToken;
 import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
+import org.apache.hadoop.security.authorize.AuthorizationException;
+import org.apache.hadoop.security.authorize.ProxyUsers;
 import org.apache.hadoop.security.token.Token;
 import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenIdentifier;
 import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager;
 import org.apache.hadoop.util.HttpExceptionUtils;
 import org.codehaus.jackson.map.ObjectMapper;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.core.MediaType;
-import java.io.IOException;
-import java.io.Writer;
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
+import com.google.common.annotations.VisibleForTesting;
 
 /**
  * An {@link AuthenticationHandler} that implements Kerberos SPNEGO mechanism
@@ -188,6 +192,19 @@ public abstract class DelegationTokenAuthenticationHandler
           UserGroupInformation requestUgi = (token != null)
               ? UserGroupInformation.createRemoteUser(token.getUserName())
               : null;
+          // Create the proxy user if doAsUser exists
+          String doAsUser = DelegationTokenAuthenticationFilter.getDoAs(request);
+          if (requestUgi != null && doAsUser != null) {
+            requestUgi = UserGroupInformation.createProxyUser(
+                doAsUser, requestUgi);
+            try {
+              ProxyUsers.authorize(requestUgi, request.getRemoteHost());
+            } catch (AuthorizationException ex) {
+              HttpExceptionUtils.createServletExceptionResponse(response,
+                  HttpServletResponse.SC_FORBIDDEN, ex);
+              return false;
+            }
+          }
           Map map = null;
           switch (dtOp) {
             case GETDELEGATIONTOKEN:

http://git-wip-us.apache.org/repos/asf/hadoop/blob/db2bfed8/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/web/DelegationTokenAuthenticator.java
----------------------------------------------------------------------
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 c614ee3..d93f7ac 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
@@ -136,14 +136,35 @@ public abstract class DelegationTokenAuthenticator implements Authenticator
{
    * supported.
    * @param token the authentication token being used for the user where the
    * Delegation token will be stored.
+   * @param renewer the renewer user.
    * @throws IOException if an IO error occurred.
    * @throws AuthenticationException if an authentication exception occurred.
    */
   public Token<AbstractDelegationTokenIdentifier> getDelegationToken(URL url,
       AuthenticatedURL.Token token, String renewer)
       throws IOException, AuthenticationException {
+   return getDelegationToken(url, token, renewer, null);
+  }
+
+  /**
+   * Requests a delegation token using the configured <code>Authenticator</code>
+   * for authentication.
+   *
+   * @param url the URL to get the delegation token from. Only HTTP/S URLs are
+   * supported.
+   * @param token the authentication token being used for the user where the
+   * Delegation token will be stored.
+   * @param renewer the renewer user.
+   * @param doAsUser the user to do as, which will be the token owner.
+   * @throws IOException if an IO error occurred.
+   * @throws AuthenticationException if an authentication exception occurred.
+   */
+  public Token<AbstractDelegationTokenIdentifier> getDelegationToken(URL url,
+      AuthenticatedURL.Token token, String renewer, String doAsUser)
+      throws IOException, AuthenticationException {
     Map json = doDelegationTokenOperation(url, token,
-        DelegationTokenOperation.GETDELEGATIONTOKEN, renewer, null, true);
+        DelegationTokenOperation.GETDELEGATIONTOKEN, renewer, null, true,
+        doAsUser);
     json = (Map) json.get(DELEGATION_TOKEN_JSON);
     String tokenStr = (String) json.get(DELEGATION_TOKEN_URL_STRING_JSON);
     Token<AbstractDelegationTokenIdentifier> dToken =
@@ -169,8 +190,27 @@ public abstract class DelegationTokenAuthenticator implements Authenticator
{
       AuthenticatedURL.Token token,
       Token<AbstractDelegationTokenIdentifier> dToken)
       throws IOException, AuthenticationException {
+    return renewDelegationToken(url, token, dToken, null);
+  }
+
+  /**
+   * Renews a delegation token from the server end-point using the
+   * configured <code>Authenticator</code> for authentication.
+   *
+   * @param url the URL to renew the delegation token from. Only HTTP/S URLs are
+   * supported.
+   * @param token the authentication token with the Delegation Token to renew.
+   * @param doAsUser the user to do as, which will be the token owner.
+   * @throws IOException if an IO error occurred.
+   * @throws AuthenticationException if an authentication exception occurred.
+   */
+  public long renewDelegationToken(URL url,
+      AuthenticatedURL.Token token,
+      Token<AbstractDelegationTokenIdentifier> dToken, String doAsUser)
+      throws IOException, AuthenticationException {
     Map json = doDelegationTokenOperation(url, token,
-        DelegationTokenOperation.RENEWDELEGATIONTOKEN, null, dToken, true);
+        DelegationTokenOperation.RENEWDELEGATIONTOKEN, null, dToken, true,
+        doAsUser);
     return (Long) json.get(RENEW_DELEGATION_TOKEN_JSON);
   }
 
@@ -187,9 +227,27 @@ public abstract class DelegationTokenAuthenticator implements Authenticator
{
       AuthenticatedURL.Token token,
       Token<AbstractDelegationTokenIdentifier> dToken)
       throws IOException {
+    cancelDelegationToken(url, token, dToken, null);
+  }
+
+  /**
+   * Cancels a delegation token from the server end-point. It does not require
+   * being authenticated by the configured <code>Authenticator</code>.
+   *
+   * @param url the URL to cancel the delegation token from. Only HTTP/S URLs
+   * are supported.
+   * @param token the authentication token with the Delegation Token to cancel.
+   * @param doAsUser the user to do as, which will be the token owner.
+   * @throws IOException if an IO error occurred.
+   */
+  public void cancelDelegationToken(URL url,
+      AuthenticatedURL.Token token,
+      Token<AbstractDelegationTokenIdentifier> dToken, String doAsUser)
+      throws IOException {
     try {
       doDelegationTokenOperation(url, token,
-          DelegationTokenOperation.CANCELDELEGATIONTOKEN, null, dToken, false);
+          DelegationTokenOperation.CANCELDELEGATIONTOKEN, null, dToken, false,
+          doAsUser);
     } catch (AuthenticationException ex) {
       throw new IOException("This should not happen: " + ex.getMessage(), ex);
     }
@@ -197,7 +255,7 @@ public abstract class DelegationTokenAuthenticator implements Authenticator
{
 
   private Map doDelegationTokenOperation(URL url,
       AuthenticatedURL.Token token, DelegationTokenOperation operation,
-      String renewer, Token<?> dToken, boolean hasResponse)
+      String renewer, Token<?> dToken, boolean hasResponse, String doAsUser)
       throws IOException, AuthenticationException {
     Map ret = null;
     Map<String, String> params = new HashMap<String, String>();
@@ -208,6 +266,11 @@ public abstract class DelegationTokenAuthenticator implements Authenticator
{
     if (dToken != null) {
       params.put(TOKEN_PARAM, dToken.encodeToUrlString());
     }
+    // proxyuser
+    if (doAsUser != null) {
+      params.put(DelegationTokenAuthenticatedURL.DO_AS,
+          URLEncoder.encode(doAsUser, "UTF-8"));
+    }
     String urlStr = url.toExternalForm();
     StringBuilder sb = new StringBuilder(urlStr);
     String separator = (urlStr.contains("?")) ? "&" : "?";

http://git-wip-us.apache.org/repos/asf/hadoop/blob/db2bfed8/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 189a334..87c3105 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
@@ -52,6 +52,9 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.Writer;
@@ -648,6 +651,16 @@ public class TestWebDelegationToken {
           "token-kind");
       return conf;
     }
+
+    @Override
+    protected org.apache.hadoop.conf.Configuration getProxyuserConfiguration(
+        FilterConfig filterConfig) throws ServletException {
+      org.apache.hadoop.conf.Configuration conf =
+          new org.apache.hadoop.conf.Configuration(false);
+      conf.set("proxyuser.client.users", OK_USER);
+      conf.set("proxyuser.client.hosts", "localhost");
+      return conf;
+    }
   }
 
   private static class KerberosConfiguration extends Configuration {
@@ -713,6 +726,19 @@ public class TestWebDelegationToken {
 
   @Test
   public void testKerberosDelegationTokenAuthenticator() throws Exception {
+    testKerberosDelegationTokenAuthenticator(false);
+  }
+
+  @Test
+  public void testKerberosDelegationTokenAuthenticatorWithDoAs()
+      throws Exception {
+    testKerberosDelegationTokenAuthenticator(true);
+  }
+
+  private void testKerberosDelegationTokenAuthenticator(
+      final boolean doAs) throws Exception {
+    final String doAsUser = doAs ? OK_USER : null;
+
     // setting hadoop security to kerberos
     org.apache.hadoop.conf.Configuration conf =
         new org.apache.hadoop.conf.Configuration();
@@ -742,7 +768,7 @@ public class TestWebDelegationToken {
       final URL url = new URL(getJettyURL() + "/foo/bar");
 
       try {
-        aUrl.getDelegationToken(url, token, FOO_USER);
+        aUrl.getDelegationToken(url, token, FOO_USER, doAsUser);
         Assert.fail();
       } catch (AuthenticationException ex) {
         Assert.assertTrue(ex.getMessage().contains("GSSException"));
@@ -752,25 +778,41 @@ public class TestWebDelegationToken {
           new Callable<Void>() {
             @Override
             public Void call() throws Exception {
-              aUrl.getDelegationToken(url, token, "client");
+              aUrl.getDelegationToken(
+                  url, token, doAs ? doAsUser : "client", doAsUser);
               Assert.assertNotNull(token.getDelegationToken());
+              Assert.assertEquals(new Text("token-kind"),
+                  token.getDelegationToken().getKind());
+              // Make sure the token belongs to the right owner
+              ByteArrayInputStream buf = new ByteArrayInputStream(
+                  token.getDelegationToken().getIdentifier());
+              DataInputStream dis = new DataInputStream(buf);
+              DelegationTokenIdentifier id =
+                  new DelegationTokenIdentifier(new Text("token-kind"));
+              id.readFields(dis);
+              dis.close();
+              Assert.assertEquals(
+                  doAs ? new Text(OK_USER) : new Text("client"), id.getOwner());
+              if (doAs) {
+                Assert.assertEquals(new Text("client"), id.getRealUser());
+              }
 
-              aUrl.renewDelegationToken(url, token);
+              aUrl.renewDelegationToken(url, token, doAsUser);
               Assert.assertNotNull(token.getDelegationToken());
 
-              aUrl.getDelegationToken(url, token, FOO_USER);
+              aUrl.getDelegationToken(url, token, FOO_USER, doAsUser);
               Assert.assertNotNull(token.getDelegationToken());
 
               try {
-                aUrl.renewDelegationToken(url, token);
+                aUrl.renewDelegationToken(url, token, doAsUser);
                 Assert.fail();
               } catch (Exception ex) {
                 Assert.assertTrue(ex.getMessage().contains("403"));
               }
 
-              aUrl.getDelegationToken(url, token, FOO_USER);
+              aUrl.getDelegationToken(url, token, FOO_USER, doAsUser);
 
-              aUrl.cancelDelegationToken(url, token);
+              aUrl.cancelDelegationToken(url, token, doAsUser);
               Assert.assertNull(token.getDelegationToken());
 
               return null;


Mime
View raw message