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

View File

@ -19,10 +19,7 @@
package org.apache.hadoop.ipc;
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@ -44,6 +41,7 @@
import org.apache.hadoop.io.Text;
import org.apache.hadoop.ipc.Client.ConnectionId;
import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.KerberosInfo;
import org.apache.hadoop.security.SaslInputStream;
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.");
}
// insecure -> insecure
@Test
public void testDigestAuthMethodSecureServer() throws Exception {
checkDigestAuthMethod(true);
public void testInsecureClientInsecureServer() throws Exception {
assertEquals(AuthenticationMethod.SIMPLE,
getAuthMethod(false, false, false));
}
@Test
public void testDigestAuthMethodInsecureServer() throws Exception {
checkDigestAuthMethod(false);
public void testInsecureClientInsecureServerWithToken() throws Exception {
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();
Server server = new RPC.Builder(conf).setProtocol(TestSaslProtocol.class)
.setInstance(new TestSaslImpl()).setBindAddress(ADDRESS).setPort(0)
.setNumHandlers(5).setVerbose(true).setSecretManager(sm).build();
if (secureServer) {
if (isSecureServer) {
server.enableSecurity();
} else {
server.disableSecurity();
@ -474,31 +549,37 @@ private void checkDigestAuthMethod(boolean secureServer) throws Exception {
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);
if (useToken) {
TestTokenIdentifier tokenId = new TestTokenIdentifier(
new Text(current.getUserName()));
Token<TestTokenIdentifier> token =
new Token<TestTokenIdentifier>(tokenId, sm);
SecurityUtil.setTokenService(token, addr);
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
public Object run() throws IOException {
public AuthenticationMethod run() throws IOException {
TestSaslProtocol proxy = null;
try {
proxy = (TestSaslProtocol) RPC.getProxy(TestSaslProtocol.class,
TestSaslProtocol.versionID, addr, conf);
Assert.assertEquals(AuthenticationMethod.TOKEN, proxy.getAuthMethod());
return proxy.getAuthMethod();
} finally {
if (proxy != null) {
RPC.stopProxy(proxy);
}
}
return null;
}
});
} finally {
server.stop();
}
}
public static void main(String[] args) throws Exception {
System.out.println("Testing Kerberos authentication over RPC");