HADOOP-9789. Support server advertised kerberos principals (daryn)
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1512380 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
52f11f7091
commit
e6c1f2233a
|
@ -338,6 +338,8 @@ Release 2.1.1-beta - UNRELEASED
|
|||
|
||||
HADOOP-9672. Upgrade Avro dependency to 1.7.4. (sandy via kihwal)
|
||||
|
||||
HADOOP-9789. Support server advertised kerberos principals (daryn)
|
||||
|
||||
OPTIMIZATIONS
|
||||
|
||||
BUG FIXES
|
||||
|
|
|
@ -33,6 +33,7 @@ import java.nio.ByteBuffer;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
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.InterfaceStability;
|
||||
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.RpcResponseMessageWrapper;
|
||||
import org.apache.hadoop.ipc.RPC.RpcKind;
|
||||
|
@ -280,9 +282,8 @@ public class SaslRpcClient {
|
|||
* @return String of the server's principal
|
||||
* @throws IOException - error determining configured principal
|
||||
*/
|
||||
|
||||
// try to get the configured principal for the remote server
|
||||
private String getServerPrincipal(SaslAuth authType) throws IOException {
|
||||
@VisibleForTesting
|
||||
String getServerPrincipal(SaslAuth authType) throws IOException {
|
||||
KerberosInfo krbInfo = SecurityUtil.getKerberosInfo(protocol, conf);
|
||||
LOG.debug("Get kerberos info proto:"+protocol+" info:"+krbInfo);
|
||||
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="
|
||||
+ protocol.getCanonicalName());
|
||||
}
|
||||
// construct the expected principal from the config
|
||||
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");
|
||||
// construct server advertised principal for comparision
|
||||
String serverPrincipal = new KerberosPrincipal(
|
||||
authType.getProtocol() + "/" + authType.getServerId()).getName();
|
||||
boolean isPrincipalValid = false;
|
||||
|
||||
// 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
|
||||
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)) {
|
||||
if (!isPrincipalValid) {
|
||||
throw new IllegalArgumentException(
|
||||
"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.ipc.Server;
|
||||
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.TokenIdentifier;
|
||||
import org.apache.hadoop.security.token.SecretManager.InvalidToken;
|
||||
|
@ -104,12 +103,12 @@ public class SaslRpcServer {
|
|||
String fullName = UserGroupInformation.getCurrentUser().getUserName();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Kerberos principal name is " + fullName);
|
||||
KerberosName krbName = new KerberosName(fullName);
|
||||
serverId = krbName.getHostName();
|
||||
if (serverId == null) {
|
||||
serverId = "";
|
||||
}
|
||||
protocol = krbName.getServiceName();
|
||||
// don't use KerberosName because we don't want auth_to_local
|
||||
String[] parts = fullName.split("[/@]", 2);
|
||||
protocol = parts[0];
|
||||
// should verify service host is present here rather than in create()
|
||||
// but lazy tests are using a UGI that isn't a SPN...
|
||||
serverId = (parts.length < 2) ? "" : parts[1];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -824,14 +824,13 @@ public class TestSaslRPC {
|
|||
final AuthMethod serverAuth,
|
||||
final UseToken tokenType) throws Exception {
|
||||
|
||||
String currentUser = UserGroupInformation.getCurrentUser().getUserName();
|
||||
|
||||
final Configuration serverConf = new Configuration(conf);
|
||||
serverConf.set(HADOOP_SECURITY_AUTHENTICATION, serverAuth.toString());
|
||||
UserGroupInformation.setConfiguration(serverConf);
|
||||
|
||||
final UserGroupInformation serverUgi =
|
||||
UserGroupInformation.createRemoteUser(currentUser + "-SERVER/localhost@NONE");
|
||||
final UserGroupInformation serverUgi = (serverAuth == KERBEROS)
|
||||
? UserGroupInformation.createRemoteUser("server/localhost@NONE")
|
||||
: UserGroupInformation.createRemoteUser("server");
|
||||
serverUgi.setAuthenticationMethod(serverAuth);
|
||||
|
||||
final TestTokenSecretManager sm = new TestTokenSecretManager();
|
||||
|
@ -866,7 +865,7 @@ public class TestSaslRPC {
|
|||
UserGroupInformation.setConfiguration(clientConf);
|
||||
|
||||
final UserGroupInformation clientUgi =
|
||||
UserGroupInformation.createRemoteUser(currentUser + "-CLIENT");
|
||||
UserGroupInformation.createRemoteUser("client");
|
||||
clientUgi.setAuthenticationMethod(clientAuth);
|
||||
|
||||
final InetSocketAddress addr = NetUtils.getConnectAddress(server);
|
||||
|
|
Loading…
Reference in New Issue