diff --git security/src/main/java/org/apache/hadoop/hbase/ipc/SecureClient.java security/src/main/java/org/apache/hadoop/hbase/ipc/SecureClient.java index d115928..38c237f 100644 --- security/src/main/java/org/apache/hadoop/hbase/ipc/SecureClient.java +++ security/src/main/java/org/apache/hadoop/hbase/ipc/SecureClient.java @@ -18,9 +18,26 @@ package org.apache.hadoop.hbase.ipc; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.SocketTimeoutException; +import java.security.PrivilegedExceptionAction; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import javax.net.SocketFactory; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.security.HBaseMultiRealmUserAuthentication; import org.apache.hadoop.hbase.security.HBaseSaslRpcClient; import org.apache.hadoop.hbase.security.HBaseSaslRpcServer.AuthMethod; import org.apache.hadoop.hbase.security.KerberosInfo; @@ -28,10 +45,14 @@ import org.apache.hadoop.hbase.security.TokenInfo; import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.security.token.AuthenticationTokenIdentifier; import org.apache.hadoop.hbase.security.token.AuthenticationTokenSelector; -import org.apache.hadoop.hbase.util.PoolMap; -import org.apache.hadoop.io.*; +import org.apache.hadoop.io.DataOutputBuffer; +import org.apache.hadoop.io.IOUtils; +import org.apache.hadoop.io.Text; +import org.apache.hadoop.io.Writable; +import org.apache.hadoop.io.WritableUtils; import org.apache.hadoop.ipc.RemoteException; import org.apache.hadoop.net.NetUtils; +import org.apache.hadoop.security.MultiRealmUserAuthentication; import org.apache.hadoop.security.SecurityUtil; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.token.Token; @@ -39,20 +60,7 @@ import org.apache.hadoop.security.token.TokenIdentifier; import org.apache.hadoop.security.token.TokenSelector; import org.apache.hadoop.util.ReflectionUtils; -import javax.net.SocketFactory; import javax.security.sasl.SaslException; -import java.io.*; -import java.net.*; -import java.security.PrivilegedExceptionAction; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Random; -import java.util.concurrent.ConcurrentSkipListMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; /** * A client for an IPC service, which support SASL authentication of connections @@ -131,8 +139,18 @@ public class SecureClient extends HBaseClient { authMethod = AuthMethod.SIMPLE; } else if (token != null) { authMethod = AuthMethod.DIGEST; - } else { - authMethod = AuthMethod.KERBEROS; + } else if (MultiRealmUserAuthentication.isAUserInADifferentRealm ( + ticket.getUGI(), conf) ){ + authMethod = AuthMethod.KERBEROS_USER_REALM; + serverPrincipal = + HBaseMultiRealmUserAuthentication.replaceRealmWithUserRealm(serverPrincipal, conf); + if (LOG.isDebugEnabled()){ + LOG.debug("AuthMehod is KERBEROS_USER_REALM and serverPrincipal is changed to " + + serverPrincipal); + } + } + else { + authMethod = AuthMethod.KERBEROS; } header = new SecureConnectionHeader( @@ -161,7 +179,8 @@ public class SecureClient extends HBaseClient { UserGroupInformation currentUser = UserGroupInformation.getCurrentUser(); UserGroupInformation realUser = currentUser.getRealUser(); - return authMethod == AuthMethod.KERBEROS && + return (authMethod == AuthMethod.KERBEROS || + authMethod == AuthMethod.KERBEROS_USER_REALM) && loginUser != null && //Make sure user logged in using Kerberos either keytab or TGT loginUser.hasKerberosCredentials() && @@ -269,7 +288,8 @@ public class SecureClient extends HBaseClient { final InputStream in2 = inStream; final OutputStream out2 = outStream; User ticket = remoteId.getTicket(); - if (authMethod == AuthMethod.KERBEROS) { + if (authMethod == AuthMethod.KERBEROS || + authMethod == AuthMethod.KERBEROS_USER_REALM) { UserGroupInformation ugi = ticket.getUGI(); if (ugi != null && ugi.getRealUser() != null) { ticket = User.create(ugi.getRealUser()); diff --git security/src/main/java/org/apache/hadoop/hbase/ipc/SecureConnectionHeader.java security/src/main/java/org/apache/hadoop/hbase/ipc/SecureConnectionHeader.java index 5060821..d2c83e6 100644 --- security/src/main/java/org/apache/hadoop/hbase/ipc/SecureConnectionHeader.java +++ security/src/main/java/org/apache/hadoop/hbase/ipc/SecureConnectionHeader.java @@ -80,7 +80,8 @@ class SecureConnectionHeader extends ConnectionHeader { Text.writeString(out, (protocol == null) ? "" : protocol); if (user != null) { UserGroupInformation ugi = user.getUGI(); - if (authMethod == AuthMethod.KERBEROS) { + if (authMethod == AuthMethod.KERBEROS || + authMethod == AuthMethod.KERBEROS_USER_REALM) { // Send effective user for Kerberos auth out.writeBoolean(true); out.writeUTF(ugi.getUserName()); diff --git security/src/main/java/org/apache/hadoop/hbase/ipc/SecureServer.java security/src/main/java/org/apache/hadoop/hbase/ipc/SecureServer.java index 3448d99..fb4d2f7 100644 --- security/src/main/java/org/apache/hadoop/hbase/ipc/SecureServer.java +++ security/src/main/java/org/apache/hadoop/hbase/ipc/SecureServer.java @@ -47,21 +47,10 @@ import org.apache.hadoop.security.token.SecretManager.InvalidToken; import org.apache.hadoop.security.token.TokenIdentifier; import org.apache.hadoop.util.ReflectionUtils; import org.apache.hadoop.util.StringUtils; +import org.apache.hadoop.hbase.security.HBaseMultiRealmUserAuthentication; import com.google.common.collect.ImmutableSet; -import javax.security.sasl.Sasl; -import javax.security.sasl.SaslException; -import javax.security.sasl.SaslServer; -import java.io.*; -import java.net.*; -import java.nio.ByteBuffer; -import java.nio.channels.*; -import java.security.PrivilegedExceptionAction; -import java.util.*; - -import static org.apache.hadoop.fs.CommonConfigurationKeys.HADOOP_SECURITY_AUTHORIZATION; - /** * An abstract IPC service, supporting SASL authentication of connections, * using GSSAPI for Kerberos authentication or DIGEST-MD5 for authentication @@ -275,28 +264,14 @@ public abstract class SecureServer extends HBaseServer { HBaseSaslRpcServer.SASL_PROPS, new SaslDigestCallbackHandler( secretManager, this)); break; + case KERBEROS_USER_REALM: + UserGroupInformation ugi = HBaseMultiRealmUserAuthentication. + getServerUGIForUserRealm(conf); + createSaslServer(ugi); + break; default: - UserGroupInformation current = UserGroupInformation - .getCurrentUser(); - String fullName = current.getUserName(); - if (LOG.isTraceEnabled()) { - LOG.trace("Kerberos principal name is " + fullName); - } - final String names[] = HBaseSaslRpcServer.splitKerberosName(fullName); - if (names.length != 3) { - throw new AccessControlException( - "Kerberos principal name does NOT have the expected " - + "hostname part: " + fullName); - } - current.doAs(new PrivilegedExceptionAction() { - @Override - public Object run() throws SaslException { - saslServer = Sasl.createSaslServer(AuthMethod.KERBEROS - .getMechanismName(), names[0], names[1], - HBaseSaslRpcServer.SASL_PROPS, new SaslGssCallbackHandler()); - return null; - } - }); + UserGroupInformation current = UserGroupInformation.getCurrentUser(); + createSaslServer(current); } if (saslServer == null) throw new AccessControlException( @@ -368,6 +343,28 @@ public abstract class SecureServer extends HBaseServer { } } + private void createSaslServer(UserGroupInformation ugi) + throws AccessControlException, IOException, InterruptedException { + String fullName = ugi.getUserName(); + if (LOG.isDebugEnabled()) + LOG.debug("Kerberos principal name is " + fullName); + final String names[] = HBaseSaslRpcServer.splitKerberosName(fullName); + if (names.length != 3) { + throw new AccessControlException( + "Kerberos principal name does NOT have the expected " + + "hostname part: " + fullName); + } + ugi.doAs(new PrivilegedExceptionAction() { + @Override + public Object run() throws SaslException { + saslServer = Sasl.createSaslServer(AuthMethod.KERBEROS + .getMechanismName(), names[0], names[1], + HBaseSaslRpcServer.SASL_PROPS, new SaslGssCallbackHandler()); + return null; + } + }); + } + private void doSaslReply(SaslStatus status, Writable rv, String errorClass, String error) throws IOException { saslCall.setResponse(rv, @@ -753,4 +750,4 @@ public abstract class SecureServer extends HBaseServer { protocol, getConf(), addr); } } -} \ No newline at end of file +} diff --git security/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java security/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java index 8090973..c9b1dd1 100644 --- security/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java +++ security/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java @@ -78,6 +78,7 @@ public class HBaseSaslRpcClient { HBaseSaslRpcServer.SASL_PROPS, new SaslClientCallbackHandler(token)); break; case KERBEROS: + case KERBEROS_USER_REALM: if (LOG.isDebugEnabled()) { LOG .debug("Creating SASL " + AuthMethod.KERBEROS.getMechanismName() diff --git security/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcServer.java security/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcServer.java index 5ffbb4f..ef46f85 100644 --- security/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcServer.java +++ security/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcServer.java @@ -136,7 +136,9 @@ public class HBaseSaslRpcServer { public static enum AuthMethod { SIMPLE((byte) 80, "", AuthenticationMethod.SIMPLE), KERBEROS((byte) 81, "GSSAPI", AuthenticationMethod.KERBEROS), - DIGEST((byte) 82, "DIGEST-MD5", AuthenticationMethod.TOKEN); + DIGEST((byte) 82, "DIGEST-MD5", AuthenticationMethod.TOKEN), + KERBEROS_USER_REALM((byte) 83, "GSSAPI", AuthenticationMethod.KERBEROS); + /** The code for this method. */ public final byte code;