HADOOP-8784. Improve IPC.Client's token use (daryn)

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1397634 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Daryn Sharp 2012-10-12 16:27:26 +00:00
parent 89b66da42c
commit 22ef03bc76
3 changed files with 124 additions and 46 deletions

View File

@ -312,6 +312,8 @@ Release 2.0.3-alpha - Unreleased
HADOOP-8912. Add .gitattributes file to prevent CRLF and LF mismatches HADOOP-8912. Add .gitattributes file to prevent CRLF and LF mismatches
for source and text files. (Raja Aluri via suresh) for source and text files. (Raja Aluri via suresh)
HADOOP-8784. Improve IPC.Client's token use (daryn)
OPTIMIZATIONS OPTIMIZATIONS
HADOOP-8866. SampleQuantiles#query is O(N^2) instead of O(N). (Andrew Wang HADOOP-8866. SampleQuantiles#query is O(N^2) instead of O(N). (Andrew Wang

View File

@ -225,7 +225,6 @@ private class Connection extends Thread {
private IpcConnectionContextProto connectionContext; // connection context private IpcConnectionContextProto connectionContext; // connection context
private final ConnectionId remoteId; // connection id private final ConnectionId remoteId; // connection id
private AuthMethod authMethod; // authentication method private AuthMethod authMethod; // authentication method
private boolean useSasl;
private Token<? extends TokenIdentifier> token; private Token<? extends TokenIdentifier> token;
private SaslRpcClient saslRpcClient; private SaslRpcClient saslRpcClient;
@ -270,8 +269,7 @@ public Connection(ConnectionId remoteId) throws IOException {
UserGroupInformation ticket = remoteId.getTicket(); UserGroupInformation ticket = remoteId.getTicket();
Class<?> protocol = remoteId.getProtocol(); Class<?> protocol = remoteId.getProtocol();
this.useSasl = UserGroupInformation.isSecurityEnabled(); if (protocol != null) {
if (useSasl && protocol != null) {
TokenInfo tokenInfo = SecurityUtil.getTokenInfo(protocol, conf); TokenInfo tokenInfo = SecurityUtil.getTokenInfo(protocol, conf);
if (tokenInfo != null) { if (tokenInfo != null) {
TokenSelector<? extends TokenIdentifier> tokenSelector = null; TokenSelector<? extends TokenIdentifier> tokenSelector = null;
@ -296,12 +294,12 @@ public Connection(ConnectionId remoteId) throws IOException {
} }
} }
if (!useSasl) { if (token != null) {
authMethod = AuthMethod.SIMPLE;
} else if (token != null) {
authMethod = AuthMethod.DIGEST; authMethod = AuthMethod.DIGEST;
} else { } else if (UserGroupInformation.isSecurityEnabled()) {
authMethod = AuthMethod.KERBEROS; authMethod = AuthMethod.KERBEROS;
} else {
authMethod = AuthMethod.SIMPLE;
} }
connectionContext = ProtoUtil.makeIpcConnectionContext( connectionContext = ProtoUtil.makeIpcConnectionContext(
@ -576,15 +574,13 @@ private synchronized void setupIOstreams() throws InterruptedException {
InputStream inStream = NetUtils.getInputStream(socket); InputStream inStream = NetUtils.getInputStream(socket);
OutputStream outStream = NetUtils.getOutputStream(socket); OutputStream outStream = NetUtils.getOutputStream(socket);
writeConnectionHeader(outStream); writeConnectionHeader(outStream);
if (useSasl) { if (authMethod != AuthMethod.SIMPLE) {
final InputStream in2 = inStream; final InputStream in2 = inStream;
final OutputStream out2 = outStream; final OutputStream out2 = outStream;
UserGroupInformation ticket = remoteId.getTicket(); UserGroupInformation ticket = remoteId.getTicket();
if (authMethod == AuthMethod.KERBEROS) {
if (ticket.getRealUser() != null) { if (ticket.getRealUser() != null) {
ticket = ticket.getRealUser(); ticket = ticket.getRealUser();
} }
}
boolean continueSasl = false; boolean continueSasl = false;
try { try {
continueSasl = ticket continueSasl = ticket
@ -614,7 +610,6 @@ public Boolean run() throws IOException {
connectionContext.getProtocol(), connectionContext.getProtocol(),
ProtoUtil.getUgi(connectionContext.getUserInfo()), ProtoUtil.getUgi(connectionContext.getUserInfo()),
authMethod); authMethod);
useSasl = false;
} }
} }
@ -1174,7 +1169,7 @@ public Writable call(RPC.RpcKind rpcKind, Writable rpcRequest,
call.error); call.error);
} }
} else { } else {
return call.rpcResponse; return call.getRpcResult();
} }
} }
} }

View File

@ -19,10 +19,7 @@
package org.apache.hadoop.ipc; package org.apache.hadoop.ipc;
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION; import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.*;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.DataInput; import java.io.DataInput;
import java.io.DataOutput; import java.io.DataOutput;
import java.io.IOException; import java.io.IOException;
@ -44,6 +41,7 @@
import org.apache.hadoop.io.Text; import org.apache.hadoop.io.Text;
import org.apache.hadoop.ipc.Client.ConnectionId; import org.apache.hadoop.ipc.Client.ConnectionId;
import org.apache.hadoop.net.NetUtils; import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.KerberosInfo; import org.apache.hadoop.security.KerberosInfo;
import org.apache.hadoop.security.SaslInputStream; import org.apache.hadoop.security.SaslInputStream;
import org.apache.hadoop.security.SaslRpcClient; import org.apache.hadoop.security.SaslRpcClient;
@ -450,22 +448,99 @@ static void testKerberosRpc(String principal, String keytab) throws Exception {
System.out.println("Test is successful."); System.out.println("Test is successful.");
} }
// insecure -> insecure
@Test @Test
public void testDigestAuthMethodSecureServer() throws Exception { public void testInsecureClientInsecureServer() throws Exception {
checkDigestAuthMethod(true); assertEquals(AuthenticationMethod.SIMPLE,
getAuthMethod(false, false, false));
} }
@Test @Test
public void testDigestAuthMethodInsecureServer() throws Exception { public void testInsecureClientInsecureServerWithToken() throws Exception {
checkDigestAuthMethod(false); assertEquals(AuthenticationMethod.TOKEN,
getAuthMethod(false, false, true));
} }
private void checkDigestAuthMethod(boolean secureServer) throws Exception { // insecure -> secure
@Test
public void testInsecureClientSecureServer() throws Exception {
RemoteException e = null;
try {
getAuthMethod(false, true, false);
} catch (RemoteException re) {
e = re;
}
assertNotNull(e);
assertEquals(AccessControlException.class.getName(), e.getClassName());
}
@Test
public void testInsecureClientSecureServerWithToken() throws Exception {
assertEquals(AuthenticationMethod.TOKEN,
getAuthMethod(false, true, true));
}
// secure -> secure
@Test
public void testSecureClientSecureServer() throws Exception {
/* Should be this when multiple secure auths are supported and we can
* dummy one out:
* assertEquals(AuthenticationMethod.SECURE_AUTH_METHOD,
* getAuthMethod(true, true, false));
*/
try {
getAuthMethod(true, true, false);
} catch (IOException ioe) {
// can't actually test kerberos w/o kerberos...
String expectedError = "Failed to specify server's Kerberos principal";
String actualError = ioe.getMessage();
assertTrue("["+actualError+"] doesn't start with ["+expectedError+"]",
actualError.contains(expectedError));
}
}
@Test
public void testSecureClientSecureServerWithToken() throws Exception {
assertEquals(AuthenticationMethod.TOKEN,
getAuthMethod(true, true, true));
}
// secure -> insecure
@Test
public void testSecureClientInsecureServerWithToken() throws Exception {
assertEquals(AuthenticationMethod.TOKEN,
getAuthMethod(true, false, true));
}
@Test
public void testSecureClientInsecureServer() throws Exception {
/* Should be this when multiple secure auths are supported and we can
* dummy one out:
* assertEquals(AuthenticationMethod.SIMPLE
* getAuthMethod(true, false, false));
*/
try {
getAuthMethod(true, false, false);
} catch (IOException ioe) {
// can't actually test kerberos w/o kerberos...
String expectedError = "Failed to specify server's Kerberos principal";
String actualError = ioe.getMessage();
assertTrue("["+actualError+"] doesn't start with ["+expectedError+"]",
actualError.contains(expectedError));
}
}
private AuthenticationMethod getAuthMethod(final boolean isSecureClient,
final boolean isSecureServer,
final boolean useToken
) throws Exception {
TestTokenSecretManager sm = new TestTokenSecretManager(); TestTokenSecretManager sm = new TestTokenSecretManager();
Server server = new RPC.Builder(conf).setProtocol(TestSaslProtocol.class) Server server = new RPC.Builder(conf).setProtocol(TestSaslProtocol.class)
.setInstance(new TestSaslImpl()).setBindAddress(ADDRESS).setPort(0) .setInstance(new TestSaslImpl()).setBindAddress(ADDRESS).setPort(0)
.setNumHandlers(5).setVerbose(true).setSecretManager(sm).build(); .setNumHandlers(5).setVerbose(true).setSecretManager(sm).build();
if (secureServer) { if (isSecureServer) {
server.enableSecurity(); server.enableSecurity();
} else { } else {
server.disableSecurity(); server.disableSecurity();
@ -474,31 +549,37 @@ private void checkDigestAuthMethod(boolean secureServer) throws Exception {
final UserGroupInformation current = UserGroupInformation.getCurrentUser(); final UserGroupInformation current = UserGroupInformation.getCurrentUser();
final InetSocketAddress addr = NetUtils.getConnectAddress(server); final InetSocketAddress addr = NetUtils.getConnectAddress(server);
TestTokenIdentifier tokenId = new TestTokenIdentifier(new Text(current if (useToken) {
.getUserName())); TestTokenIdentifier tokenId = new TestTokenIdentifier(
Token<TestTokenIdentifier> token = new Token<TestTokenIdentifier>(tokenId, new Text(current.getUserName()));
sm); Token<TestTokenIdentifier> token =
new Token<TestTokenIdentifier>(tokenId, sm);
SecurityUtil.setTokenService(token, addr); SecurityUtil.setTokenService(token, addr);
current.addToken(token); current.addToken(token);
}
current.doAs(new PrivilegedExceptionAction<Object>() { conf.set(HADOOP_SECURITY_AUTHENTICATION, isSecureClient ? "kerberos" : "simple");
UserGroupInformation.setConfiguration(conf);
try {
return current.doAs(new PrivilegedExceptionAction<AuthenticationMethod>() {
@Override @Override
public Object run() throws IOException { public AuthenticationMethod run() throws IOException {
TestSaslProtocol proxy = null; TestSaslProtocol proxy = null;
try { try {
proxy = (TestSaslProtocol) RPC.getProxy(TestSaslProtocol.class, proxy = (TestSaslProtocol) RPC.getProxy(TestSaslProtocol.class,
TestSaslProtocol.versionID, addr, conf); TestSaslProtocol.versionID, addr, conf);
Assert.assertEquals(AuthenticationMethod.TOKEN, proxy.getAuthMethod()); return proxy.getAuthMethod();
} finally { } finally {
if (proxy != null) { if (proxy != null) {
RPC.stopProxy(proxy); RPC.stopProxy(proxy);
} }
} }
return null;
} }
}); });
} finally {
server.stop(); server.stop();
} }
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
System.out.println("Testing Kerberos authentication over RPC"); System.out.println("Testing Kerberos authentication over RPC");