merge -c 1512380 FIXES: HADOOP-9789. Support server advertised kerberos principals (daryn)
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1512381 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d90f3fbdbf
commit
02aa997ba2
|
@ -65,6 +65,8 @@ Release 2.1.1-beta - UNRELEASED
|
||||||
|
|
||||||
HADOOP-9672. Upgrade Avro dependency to 1.7.4. (sandy via kihwal)
|
HADOOP-9672. Upgrade Avro dependency to 1.7.4. (sandy via kihwal)
|
||||||
|
|
||||||
|
HADOOP-9789. Support server advertised kerberos principals (daryn)
|
||||||
|
|
||||||
OPTIMIZATIONS
|
OPTIMIZATIONS
|
||||||
|
|
||||||
BUG FIXES
|
BUG FIXES
|
||||||
|
|
|
@ -33,6 +33,7 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.security.auth.callback.Callback;
|
import javax.security.auth.callback.Callback;
|
||||||
import javax.security.auth.callback.CallbackHandler;
|
import javax.security.auth.callback.CallbackHandler;
|
||||||
|
@ -51,6 +52,7 @@ import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.classification.InterfaceStability;
|
import org.apache.hadoop.classification.InterfaceStability;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.fs.GlobPattern;
|
||||||
import org.apache.hadoop.ipc.ProtobufRpcEngine.RpcRequestMessageWrapper;
|
import org.apache.hadoop.ipc.ProtobufRpcEngine.RpcRequestMessageWrapper;
|
||||||
import org.apache.hadoop.ipc.ProtobufRpcEngine.RpcResponseMessageWrapper;
|
import org.apache.hadoop.ipc.ProtobufRpcEngine.RpcResponseMessageWrapper;
|
||||||
import org.apache.hadoop.ipc.RPC.RpcKind;
|
import org.apache.hadoop.ipc.RPC.RpcKind;
|
||||||
|
@ -280,9 +282,8 @@ public class SaslRpcClient {
|
||||||
* @return String of the server's principal
|
* @return String of the server's principal
|
||||||
* @throws IOException - error determining configured principal
|
* @throws IOException - error determining configured principal
|
||||||
*/
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
// try to get the configured principal for the remote server
|
String getServerPrincipal(SaslAuth authType) throws IOException {
|
||||||
private String getServerPrincipal(SaslAuth authType) throws IOException {
|
|
||||||
KerberosInfo krbInfo = SecurityUtil.getKerberosInfo(protocol, conf);
|
KerberosInfo krbInfo = SecurityUtil.getKerberosInfo(protocol, conf);
|
||||||
LOG.debug("Get kerberos info proto:"+protocol+" info:"+krbInfo);
|
LOG.debug("Get kerberos info proto:"+protocol+" info:"+krbInfo);
|
||||||
if (krbInfo == null) { // protocol has no support for kerberos
|
if (krbInfo == null) { // protocol has no support for kerberos
|
||||||
|
@ -294,28 +295,37 @@ public class SaslRpcClient {
|
||||||
"Can't obtain server Kerberos config key from protocol="
|
"Can't obtain server Kerberos config key from protocol="
|
||||||
+ protocol.getCanonicalName());
|
+ protocol.getCanonicalName());
|
||||||
}
|
}
|
||||||
// construct the expected principal from the config
|
// construct server advertised principal for comparision
|
||||||
String confPrincipal = SecurityUtil.getServerPrincipal(
|
String serverPrincipal = new KerberosPrincipal(
|
||||||
conf.get(serverKey), serverAddr.getAddress());
|
authType.getProtocol() + "/" + authType.getServerId()).getName();
|
||||||
if (confPrincipal == null || confPrincipal.isEmpty()) {
|
boolean isPrincipalValid = false;
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Failed to specify server's Kerberos principal name");
|
// use the pattern if defined
|
||||||
|
String serverKeyPattern = conf.get(serverKey + ".pattern");
|
||||||
|
if (serverKeyPattern != null && !serverKeyPattern.isEmpty()) {
|
||||||
|
Pattern pattern = GlobPattern.compile(serverKeyPattern);
|
||||||
|
isPrincipalValid = pattern.matcher(serverPrincipal).matches();
|
||||||
|
} else {
|
||||||
|
// check that the server advertised principal matches our conf
|
||||||
|
String confPrincipal = SecurityUtil.getServerPrincipal(
|
||||||
|
conf.get(serverKey), serverAddr.getAddress());
|
||||||
|
if (confPrincipal == null || confPrincipal.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Failed to specify server's Kerberos principal name");
|
||||||
|
}
|
||||||
|
KerberosName name = new KerberosName(confPrincipal);
|
||||||
|
if (name.getHostName() == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Kerberos principal name does NOT have the expected hostname part: "
|
||||||
|
+ confPrincipal);
|
||||||
|
}
|
||||||
|
isPrincipalValid = serverPrincipal.equals(confPrincipal);
|
||||||
}
|
}
|
||||||
// ensure it looks like a host-based service principal
|
if (!isPrincipalValid) {
|
||||||
KerberosName name = new KerberosName(confPrincipal);
|
|
||||||
if (name.getHostName() == null) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Kerberos principal name does NOT have the expected hostname part: "
|
|
||||||
+ confPrincipal);
|
|
||||||
}
|
|
||||||
// check that the server advertised principal matches our conf
|
|
||||||
KerberosPrincipal serverPrincipal = new KerberosPrincipal(
|
|
||||||
authType.getProtocol() + "/" + authType.getServerId());
|
|
||||||
if (!serverPrincipal.getName().equals(confPrincipal)) {
|
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Server has invalid Kerberos principal: " + serverPrincipal);
|
"Server has invalid Kerberos principal: " + serverPrincipal);
|
||||||
}
|
}
|
||||||
return confPrincipal;
|
return serverPrincipal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@ import org.apache.hadoop.classification.InterfaceStability;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.ipc.Server;
|
import org.apache.hadoop.ipc.Server;
|
||||||
import org.apache.hadoop.ipc.Server.Connection;
|
import org.apache.hadoop.ipc.Server.Connection;
|
||||||
import org.apache.hadoop.security.authentication.util.KerberosName;
|
|
||||||
import org.apache.hadoop.security.token.SecretManager;
|
import org.apache.hadoop.security.token.SecretManager;
|
||||||
import org.apache.hadoop.security.token.TokenIdentifier;
|
import org.apache.hadoop.security.token.TokenIdentifier;
|
||||||
import org.apache.hadoop.security.token.SecretManager.InvalidToken;
|
import org.apache.hadoop.security.token.SecretManager.InvalidToken;
|
||||||
|
@ -104,12 +103,12 @@ public class SaslRpcServer {
|
||||||
String fullName = UserGroupInformation.getCurrentUser().getUserName();
|
String fullName = UserGroupInformation.getCurrentUser().getUserName();
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("Kerberos principal name is " + fullName);
|
LOG.debug("Kerberos principal name is " + fullName);
|
||||||
KerberosName krbName = new KerberosName(fullName);
|
// don't use KerberosName because we don't want auth_to_local
|
||||||
serverId = krbName.getHostName();
|
String[] parts = fullName.split("[/@]", 2);
|
||||||
if (serverId == null) {
|
protocol = parts[0];
|
||||||
serverId = "";
|
// should verify service host is present here rather than in create()
|
||||||
}
|
// but lazy tests are using a UGI that isn't a SPN...
|
||||||
protocol = krbName.getServiceName();
|
serverId = (parts.length < 2) ? "" : parts[1];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -824,14 +824,13 @@ public class TestSaslRPC {
|
||||||
final AuthMethod serverAuth,
|
final AuthMethod serverAuth,
|
||||||
final UseToken tokenType) throws Exception {
|
final UseToken tokenType) throws Exception {
|
||||||
|
|
||||||
String currentUser = UserGroupInformation.getCurrentUser().getUserName();
|
|
||||||
|
|
||||||
final Configuration serverConf = new Configuration(conf);
|
final Configuration serverConf = new Configuration(conf);
|
||||||
serverConf.set(HADOOP_SECURITY_AUTHENTICATION, serverAuth.toString());
|
serverConf.set(HADOOP_SECURITY_AUTHENTICATION, serverAuth.toString());
|
||||||
UserGroupInformation.setConfiguration(serverConf);
|
UserGroupInformation.setConfiguration(serverConf);
|
||||||
|
|
||||||
final UserGroupInformation serverUgi =
|
final UserGroupInformation serverUgi = (serverAuth == KERBEROS)
|
||||||
UserGroupInformation.createRemoteUser(currentUser + "-SERVER/localhost@NONE");
|
? UserGroupInformation.createRemoteUser("server/localhost@NONE")
|
||||||
|
: UserGroupInformation.createRemoteUser("server");
|
||||||
serverUgi.setAuthenticationMethod(serverAuth);
|
serverUgi.setAuthenticationMethod(serverAuth);
|
||||||
|
|
||||||
final TestTokenSecretManager sm = new TestTokenSecretManager();
|
final TestTokenSecretManager sm = new TestTokenSecretManager();
|
||||||
|
@ -866,7 +865,7 @@ public class TestSaslRPC {
|
||||||
UserGroupInformation.setConfiguration(clientConf);
|
UserGroupInformation.setConfiguration(clientConf);
|
||||||
|
|
||||||
final UserGroupInformation clientUgi =
|
final UserGroupInformation clientUgi =
|
||||||
UserGroupInformation.createRemoteUser(currentUser + "-CLIENT");
|
UserGroupInformation.createRemoteUser("client");
|
||||||
clientUgi.setAuthenticationMethod(clientAuth);
|
clientUgi.setAuthenticationMethod(clientAuth);
|
||||||
|
|
||||||
final InetSocketAddress addr = NetUtils.getConnectAddress(server);
|
final InetSocketAddress addr = NetUtils.getConnectAddress(server);
|
||||||
|
|
Loading…
Reference in New Issue