hadoop-common-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bor...@apache.org
Subject svn commit: r933810 - in /hadoop/common/trunk: ./ src/java/org/apache/hadoop/ipc/ src/java/org/apache/hadoop/security/ src/test/core/org/apache/hadoop/ipc/ src/test/core/org/apache/hadoop/security/
Date Tue, 13 Apr 2010 23:01:43 GMT
Author: boryas
Date: Tue Apr 13 23:01:43 2010
New Revision: 933810

URL: http://svn.apache.org/viewvc?rev=933810&view=rev
Log:
HADOOP-6580. UGI should contain authentication method.

Modified:
    hadoop/common/trunk/CHANGES.txt
    hadoop/common/trunk/src/java/org/apache/hadoop/ipc/Server.java
    hadoop/common/trunk/src/java/org/apache/hadoop/security/SaslRpcServer.java
    hadoop/common/trunk/src/java/org/apache/hadoop/security/User.java
    hadoop/common/trunk/src/java/org/apache/hadoop/security/UserGroupInformation.java
    hadoop/common/trunk/src/test/core/org/apache/hadoop/ipc/TestSaslRPC.java
    hadoop/common/trunk/src/test/core/org/apache/hadoop/security/TestUserGroupInformation.java

Modified: hadoop/common/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/CHANGES.txt?rev=933810&r1=933809&r2=933810&view=diff
==============================================================================
--- hadoop/common/trunk/CHANGES.txt (original)
+++ hadoop/common/trunk/CHANGES.txt Tue Apr 13 23:01:43 2010
@@ -68,6 +68,8 @@ Trunk (unreleased changes)
     HADOOP-6586. Log authentication and authorization failures and successes
     for RPC (boryas)
 
+    HADOOP-6580. UGI should contain authentication method. (jnp via boryas)
+
   IMPROVEMENTS
 
     HADOOP-6283. Improve the exception messages thrown by

Modified: hadoop/common/trunk/src/java/org/apache/hadoop/ipc/Server.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/java/org/apache/hadoop/ipc/Server.java?rev=933810&r1=933809&r2=933810&view=diff
==============================================================================
--- hadoop/common/trunk/src/java/org/apache/hadoop/ipc/Server.java (original)
+++ hadoop/common/trunk/src/java/org/apache/hadoop/ipc/Server.java Tue Apr 13 23:01:43 2010
@@ -72,6 +72,7 @@ import org.apache.hadoop.security.SaslRp
 import org.apache.hadoop.security.SaslRpcServer.SaslStatus;
 import org.apache.hadoop.security.SaslRpcServer.SaslDigestCallbackHandler;
 import org.apache.hadoop.security.SaslRpcServer.SaslGssCallbackHandler;
+import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.security.authorize.ProxyUsers;
 import org.apache.hadoop.security.authorize.AuthorizationException;
@@ -1084,18 +1085,32 @@ public abstract class Server {
       UserGroupInformation protocolUser = header.getUgi();
       if (!useSasl) {
         user = protocolUser;
-      } else if ((protocolUser != null)
-          && (!protocolUser.getUserName().equals(user.getUserName()))) {
-        if (authMethod == AuthMethod.DIGEST) {
-          // Not allowed to doAs if token authentication is used
-          throw new AccessControlException("Authenticated user (" + user
-              + ") doesn't match what the client claims to be (" + protocolUser
-              + ")");
-        } else {
-          //Effective user can be different from authenticated user
-          //for simple auth or kerberos auth
-          user = UserGroupInformation.createProxyUser(protocolUser
-              .getUserName(), user);
+        if (user != null) {
+          user.setAuthenticationMethod(AuthMethod.SIMPLE.authenticationMethod);
+        }
+      } else {
+        // user is authenticated
+        user.setAuthenticationMethod(authMethod.authenticationMethod);
+        //Now we check if this is a proxy user case. If the protocol user is
+        //different from the 'user', it is a proxy user scenario. However, 
+        //this is not allowed if user authenticated with DIGEST.
+        if ((protocolUser != null)
+            && (!protocolUser.getUserName().equals(user.getUserName()))) {
+          if (authMethod == AuthMethod.DIGEST) {
+            // Not allowed to doAs if token authentication is used
+            throw new AccessControlException("Authenticated user (" + user
+                + ") doesn't match what the client claims to be ("
+                + protocolUser + ")");
+          } else {
+            // Effective user can be different from authenticated user
+            // for simple auth or kerberos auth
+            // The user is the real user. Now we create a proxy user
+            UserGroupInformation realUser = user;
+            user = UserGroupInformation.createProxyUser(protocolUser
+                .getUserName(), realUser);
+            // Now the user is a proxy user, set Authentication method Proxy.
+            user.setAuthenticationMethod(AuthenticationMethod.PROXY);
+          }
         }
       }
     }

Modified: hadoop/common/trunk/src/java/org/apache/hadoop/security/SaslRpcServer.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/java/org/apache/hadoop/security/SaslRpcServer.java?rev=933810&r1=933809&r2=933810&view=diff
==============================================================================
--- hadoop/common/trunk/src/java/org/apache/hadoop/security/SaslRpcServer.java (original)
+++ hadoop/common/trunk/src/java/org/apache/hadoop/security/SaslRpcServer.java Tue Apr 13
23:01:43 2010
@@ -41,6 +41,7 @@ import org.apache.commons.logging.LogFac
 import org.apache.hadoop.ipc.Server;
 import org.apache.hadoop.security.token.SecretManager;
 import org.apache.hadoop.security.token.TokenIdentifier;
+import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
 import org.apache.hadoop.security.token.SecretManager.InvalidToken;
 
 /**
@@ -102,17 +103,20 @@ public class SaslRpcServer {
   
   /** Authentication method */
   public static enum AuthMethod {
-    SIMPLE((byte) 80, ""), // no authentication
-    KERBEROS((byte) 81, "GSSAPI"), // SASL Kerberos authentication
-    DIGEST((byte) 82, "DIGEST-MD5"); // SASL DIGEST-MD5 authentication
+    SIMPLE((byte) 80, "", AuthenticationMethod.SIMPLE),
+    KERBEROS((byte) 81, "GSSAPI", AuthenticationMethod.KERBEROS),
+    DIGEST((byte) 82, "DIGEST-MD5", AuthenticationMethod.TOKEN);
 
     /** The code for this method. */
     public final byte code;
     public final String mechanismName;
+    public final AuthenticationMethod authenticationMethod;
 
-    private AuthMethod(byte code, String mechanismName) {
+    private AuthMethod(byte code, String mechanismName, 
+                       AuthenticationMethod authMethod) {
       this.code = code;
       this.mechanismName = mechanismName;
+      this.authenticationMethod = authMethod;
     }
 
     private static final int FIRST_CODE = values()[0].code;

Modified: hadoop/common/trunk/src/java/org/apache/hadoop/security/User.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/java/org/apache/hadoop/security/User.java?rev=933810&r1=933809&r2=933810&view=diff
==============================================================================
--- hadoop/common/trunk/src/java/org/apache/hadoop/security/User.java (original)
+++ hadoop/common/trunk/src/java/org/apache/hadoop/security/User.java Tue Apr 13 23:01:43
2010
@@ -19,6 +19,8 @@ package org.apache.hadoop.security;
 
 import java.security.Principal;
 
+import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
+
 /**
  * Save the full and short name of the user as a principal. This allows us to
  * have a single type that we always look for when picking up user names.
@@ -26,8 +28,13 @@ import java.security.Principal;
 class User implements Principal {
   private final String fullName;
   private final String shortName;
+  private AuthenticationMethod authMethod = null;
 
   public User(String name) {
+    this(name, null);
+  }
+  
+  public User(String name, AuthenticationMethod authMethod) {
     fullName = name;
     int atIdx = name.indexOf('@');
     if (atIdx == -1) {
@@ -40,6 +47,7 @@ class User implements Principal {
         shortName = name.substring(0, slashIdx);
       }
     }
+    this.authMethod = authMethod;
   }
 
   /**
@@ -65,7 +73,7 @@ class User implements Principal {
     } else if (o == null || getClass() != o.getClass()) {
       return false;
     } else {
-      return fullName.equals(((User) o).fullName);
+      return ((fullName.equals(((User) o).fullName)) && (authMethod == ((User) o).authMethod));
     }
   }
   
@@ -78,4 +86,12 @@ class User implements Principal {
   public String toString() {
     return fullName;
   }
+
+  public void setAuthenticationMethod(AuthenticationMethod authMethod) {
+    this.authMethod = authMethod;
+  }
+
+  public AuthenticationMethod getAuthenticationMethod() {
+    return authMethod;
+  }
 }

Modified: hadoop/common/trunk/src/java/org/apache/hadoop/security/UserGroupInformation.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/java/org/apache/hadoop/security/UserGroupInformation.java?rev=933810&r1=933809&r2=933810&view=diff
==============================================================================
--- hadoop/common/trunk/src/java/org/apache/hadoop/security/UserGroupInformation.java (original)
+++ hadoop/common/trunk/src/java/org/apache/hadoop/security/UserGroupInformation.java Tue
Apr 13 23:01:43 2010
@@ -51,6 +51,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.SaslRpcServer.AuthMethod;
 import org.apache.hadoop.security.token.Token;
 import org.apache.hadoop.security.token.TokenIdentifier;
 
@@ -470,6 +471,15 @@ public class UserGroupInformation {
     return new UserGroupInformation(subject);
   }
 
+  public static enum AuthenticationMethod {
+    SIMPLE,
+    KERBEROS,
+    TOKEN,
+    CERTIFICATE,
+    KERBEROS_SSL,
+    PROXY;
+  }
+
   /* Create a proxy user using username of the effective user and the ugi of the
    * real user.
    *
@@ -650,6 +660,30 @@ public class UserGroupInformation {
   }
 
   /**
+   * Sets the authentication method in the subject
+   * 
+   * @param authMethod
+   */
+  public synchronized 
+  void setAuthenticationMethod(AuthenticationMethod authMethod) {
+    for (User p : subject.getPrincipals(User.class)) {
+      p.setAuthenticationMethod(authMethod);
+    }
+  }
+
+  /**
+   * Get the authentication method from the subject
+   * 
+   * @return AuthenticationMethod in the subject, null if not present.
+   */
+  public synchronized AuthenticationMethod getAuthenticationMethod() {
+    for (User p: subject.getPrincipals(User.class)) {
+      return p.getAuthenticationMethod();
+    }
+    return null;
+  }
+
+  /**
    * Compare the subjects to see if they are equal to each other.
    */
   @Override

Modified: hadoop/common/trunk/src/test/core/org/apache/hadoop/ipc/TestSaslRPC.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/test/core/org/apache/hadoop/ipc/TestSaslRPC.java?rev=933810&r1=933809&r2=933810&view=diff
==============================================================================
--- hadoop/common/trunk/src/test/core/org/apache/hadoop/ipc/TestSaslRPC.java (original)
+++ hadoop/common/trunk/src/test/core/org/apache/hadoop/ipc/TestSaslRPC.java Tue Apr 13 23:01:43
2010
@@ -25,8 +25,11 @@ import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
 import java.net.InetSocketAddress;
+import java.security.PrivilegedExceptionAction;
 import java.util.Collection;
 
+import junit.framework.Assert;
+
 import org.apache.commons.logging.*;
 import org.apache.commons.logging.impl.Log4JLogger;
 
@@ -44,6 +47,7 @@ import org.apache.hadoop.security.SaslIn
 import org.apache.hadoop.security.SaslRpcClient;
 import org.apache.hadoop.security.SaslRpcServer;
 import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
 
 import org.apache.log4j.Level;
 import org.junit.Test;
@@ -161,10 +165,14 @@ public class TestSaslRPC {
   @KerberosInfo(SERVER_PRINCIPAL_KEY)
   @TokenInfo(TestTokenSelector.class)
   public interface TestSaslProtocol extends TestRPC.TestProtocol {
+    public AuthenticationMethod getAuthMethod() throws IOException;
   }
   
   public static class TestSaslImpl extends TestRPC.TestImpl implements
       TestSaslProtocol {
+    public AuthenticationMethod getAuthMethod() throws IOException {
+      return UserGroupInformation.getCurrentUser().getAuthenticationMethod();
+    }
   }
 
   @Test
@@ -258,6 +266,43 @@ public class TestSaslRPC {
     }
   }
   
+  @Test
+  public void testDigestAuthMethod() throws Exception {
+    TestTokenSecretManager sm = new TestTokenSecretManager();
+    Server server = RPC.getServer(TestSaslProtocol.class,
+        new TestSaslImpl(), ADDRESS, 0, 5, true, conf, sm);
+    server.start();
+
+    final UserGroupInformation current = UserGroupInformation.getCurrentUser();
+    final InetSocketAddress addr = NetUtils.getConnectAddress(server);
+    TestTokenIdentifier tokenId = new TestTokenIdentifier(new Text(current
+        .getUserName()));
+    Token<TestTokenIdentifier> token = new Token<TestTokenIdentifier>(tokenId,
+        sm);
+    Text host = new Text(addr.getAddress().getHostAddress() + ":"
+        + addr.getPort());
+    token.setService(host);
+    LOG.info("Service IP address for token is " + host);
+    current.addToken(token);
+
+    current.doAs(new PrivilegedExceptionAction<Object>() {
+      public Object run() throws IOException {
+        TestSaslProtocol proxy = null;
+        try {
+          proxy = (TestSaslProtocol) RPC.getProxy(TestSaslProtocol.class,
+              TestSaslProtocol.versionID, addr, conf);
+          Assert.assertEquals(AuthenticationMethod.TOKEN, proxy.getAuthMethod());
+        } finally {
+          if (proxy != null) {
+            RPC.stopProxy(proxy);
+          }
+        }
+        return null;
+      }
+    });
+    server.stop();
+  }
+  
   public static void main(String[] args) throws Exception {
     System.out.println("Testing Kerberos authentication over RPC");
     if (args.length != 2) {

Modified: hadoop/common/trunk/src/test/core/org/apache/hadoop/security/TestUserGroupInformation.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/src/test/core/org/apache/hadoop/security/TestUserGroupInformation.java?rev=933810&r1=933809&r2=933810&view=diff
==============================================================================
--- hadoop/common/trunk/src/test/core/org/apache/hadoop/security/TestUserGroupInformation.java
(original)
+++ hadoop/common/trunk/src/test/core/org/apache/hadoop/security/TestUserGroupInformation.java
Tue Apr 13 23:01:43 2010
@@ -27,13 +27,15 @@ import static org.mockito.Mockito.mock;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.security.PrivilegedAction;
 import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
-import org.apache.hadoop.conf.Configuration;
+import junit.framework.Assert;
+
+import org.apache.hadoop.security.SaslRpcServer.AuthMethod;
+import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
 import org.apache.hadoop.security.token.Token;
 import org.apache.hadoop.security.token.TokenIdentifier;
 import org.junit.Test;
@@ -212,4 +214,51 @@ public class TestUserGroupInformation {
     assertTrue(otherSet.contains(t1));
     assertTrue(otherSet.contains(t2));
   }
+  
+  @Test
+  public void testUGIAuthMethod() throws Exception {
+    final UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
+    final AuthenticationMethod am = AuthenticationMethod.KERBEROS;
+    ugi.setAuthenticationMethod(am);
+    Assert.assertEquals(am, ugi.getAuthenticationMethod());
+    ugi.doAs(new PrivilegedExceptionAction<Object>() {
+      public Object run() throws IOException {
+        Assert.assertEquals(am, UserGroupInformation.getCurrentUser()
+            .getAuthenticationMethod());
+        return null;
+      }
+    });
+  }
+  
+  @Test
+  public void testUGIAuthMethodInRealUser() throws Exception {
+    final UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
+    UserGroupInformation proxyUgi = UserGroupInformation.createProxyUser(
+        "proxy", ugi);
+    final AuthenticationMethod am = AuthenticationMethod.KERBEROS;
+    ugi.setAuthenticationMethod(am);
+    Assert.assertEquals(am, ugi.getAuthenticationMethod());
+    Assert.assertEquals(null, proxyUgi.getAuthenticationMethod());
+    proxyUgi.setAuthenticationMethod(AuthenticationMethod.PROXY);
+    proxyUgi.doAs(new PrivilegedExceptionAction<Object>() {
+      public Object run() throws IOException {
+        Assert.assertEquals(AuthenticationMethod.PROXY, UserGroupInformation
+            .getCurrentUser().getAuthenticationMethod());
+        Assert.assertEquals(am, UserGroupInformation.getCurrentUser()
+            .getRealUser().getAuthenticationMethod());
+        return null;
+      }
+    });
+    UserGroupInformation proxyUgi2 = UserGroupInformation.createProxyUser(
+        "proxy", ugi);
+    proxyUgi2.setAuthenticationMethod(AuthenticationMethod.PROXY);
+    Assert.assertEquals(proxyUgi, proxyUgi2);
+    // Equality should work if authMethod is null
+    UserGroupInformation realugi = UserGroupInformation.getCurrentUser();
+    UserGroupInformation proxyUgi3 = UserGroupInformation.createProxyUser(
+        "proxyAnother", realugi);
+    UserGroupInformation proxyUgi4 = UserGroupInformation.createProxyUser(
+        "proxyAnother", realugi);
+    Assert.assertEquals(proxyUgi3, proxyUgi4);
+  }
 }



Mime
View raw message