YARN-320. RM should always be able to renew its own tokens. Contributed by Daryn Sharp

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1431020 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Siddharth Seth 2013-01-09 19:33:06 +00:00
parent 0ba7078ef4
commit ba5b19fb5d
3 changed files with 109 additions and 2 deletions

View File

@ -287,6 +287,9 @@ Release 0.23.6 - UNRELEASED
YARN-50. Implement renewal / cancellation of Delegation Tokens YARN-50. Implement renewal / cancellation of Delegation Tokens
(Siddharth Seth via tgraves) (Siddharth Seth via tgraves)
YARN-320. RM should always be able to renew its own tokens.
(Daryn Sharp via sseth)
Release 0.23.5 - UNRELEASED Release 0.23.5 - UNRELEASED
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -519,7 +519,7 @@ public RenewDelegationTokenResponse renewDelegationToken(
protoToken.getIdentifier().array(), protoToken.getPassword().array(), protoToken.getIdentifier().array(), protoToken.getPassword().array(),
new Text(protoToken.getKind()), new Text(protoToken.getService())); new Text(protoToken.getKind()), new Text(protoToken.getService()));
String user = UserGroupInformation.getCurrentUser().getShortUserName(); String user = getRenewerForToken(token);
long nextExpTime = rmDTSecretManager.renewToken(token, user); long nextExpTime = rmDTSecretManager.renewToken(token, user);
RenewDelegationTokenResponse renewResponse = Records RenewDelegationTokenResponse renewResponse = Records
.newRecord(RenewDelegationTokenResponse.class); .newRecord(RenewDelegationTokenResponse.class);
@ -543,7 +543,7 @@ public CancelDelegationTokenResponse cancelDelegationToken(
protoToken.getIdentifier().array(), protoToken.getPassword().array(), protoToken.getIdentifier().array(), protoToken.getPassword().array(),
new Text(protoToken.getKind()), new Text(protoToken.getService())); new Text(protoToken.getKind()), new Text(protoToken.getService()));
String user = UserGroupInformation.getCurrentUser().getShortUserName(); String user = getRenewerForToken(token);
rmDTSecretManager.cancelToken(token, user); rmDTSecretManager.cancelToken(token, user);
return Records.newRecord(CancelDelegationTokenResponse.class); return Records.newRecord(CancelDelegationTokenResponse.class);
} catch (IOException e) { } catch (IOException e) {
@ -551,6 +551,16 @@ public CancelDelegationTokenResponse cancelDelegationToken(
} }
} }
private String getRenewerForToken(Token<RMDelegationTokenIdentifier> token)
throws IOException {
UserGroupInformation user = UserGroupInformation.getCurrentUser();
UserGroupInformation loginUser = UserGroupInformation.getLoginUser();
// we can always renew our own tokens
return loginUser.getUserName().equals(user.getUserName())
? token.decodeIdentifier().getRenewer().toString()
: user.getShortUserName();
}
void refreshServiceAcls(Configuration configuration, void refreshServiceAcls(Configuration configuration,
PolicyProvider policyProvider) { PolicyProvider policyProvider) {
this.server.refreshServiceAcl(configuration, policyProvider); this.server.refreshServiceAcl(configuration, policyProvider);

View File

@ -25,6 +25,7 @@
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.security.PrivilegedExceptionAction;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -33,14 +34,19 @@
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.yarn.api.ClientRMProtocol; import org.apache.hadoop.yarn.api.ClientRMProtocol;
import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportRequest; import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportRequest;
import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportResponse; import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportResponse;
import org.apache.hadoop.yarn.api.protocolrecords.GetClusterNodesRequest; import org.apache.hadoop.yarn.api.protocolrecords.GetClusterNodesRequest;
import org.apache.hadoop.yarn.api.protocolrecords.GetQueueInfoRequest; import org.apache.hadoop.yarn.api.protocolrecords.GetQueueInfoRequest;
import org.apache.hadoop.yarn.api.protocolrecords.GetQueueInfoResponse; import org.apache.hadoop.yarn.api.protocolrecords.GetQueueInfoResponse;
import org.apache.hadoop.yarn.api.protocolrecords.RenewDelegationTokenRequest;
import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ApplicationReport; import org.apache.hadoop.yarn.api.records.ApplicationReport;
import org.apache.hadoop.yarn.api.records.DelegationToken;
import org.apache.hadoop.yarn.api.records.NodeReport; import org.apache.hadoop.yarn.api.records.NodeReport;
import org.apache.hadoop.yarn.api.records.QueueInfo; import org.apache.hadoop.yarn.api.records.QueueInfo;
import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.conf.YarnConfiguration;
@ -49,11 +55,16 @@
import org.apache.hadoop.yarn.factories.RecordFactory; import org.apache.hadoop.yarn.factories.RecordFactory;
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider; import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
import org.apache.hadoop.yarn.ipc.YarnRPC; import org.apache.hadoop.yarn.ipc.YarnRPC;
import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
import org.apache.hadoop.yarn.server.RMDelegationTokenSecretManager;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppImpl; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppImpl;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.YarnScheduler; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.YarnScheduler;
import org.apache.hadoop.yarn.util.BuilderUtils;
import org.apache.hadoop.yarn.util.Records; import org.apache.hadoop.yarn.util.Records;
import org.junit.Test; import org.junit.Test;
import org.junit.AfterClass;
import org.junit.BeforeClass;
public class TestClientRMService { public class TestClientRMService {
@ -63,6 +74,21 @@ public class TestClientRMService {
private RecordFactory recordFactory = RecordFactoryProvider private RecordFactory recordFactory = RecordFactoryProvider
.getRecordFactory(null); .getRecordFactory(null);
private static RMDelegationTokenSecretManager dtsm;
@BeforeClass
public static void setupSecretManager() throws IOException {
dtsm = new RMDelegationTokenSecretManager(60000, 60000, 60000, 60000);
dtsm.startThreads();
}
@AfterClass
public static void teardownSecretManager() {
if (dtsm != null) {
dtsm.stopThreads();
}
}
@Test @Test
public void testGetClusterNodes() throws Exception { public void testGetClusterNodes() throws Exception {
MockRM rm = new MockRM() { MockRM rm = new MockRM() {
@ -141,6 +167,74 @@ public void testGetQueueInfo() throws Exception {
Assert.assertEquals(2, applications.size()); Assert.assertEquals(2, applications.size());
} }
private static final UserGroupInformation owner =
UserGroupInformation.createRemoteUser("owner");
private static final UserGroupInformation other =
UserGroupInformation.createRemoteUser("other");
@Test
public void testTokenRenewalByOwner() throws Exception {
owner.doAs(new PrivilegedExceptionAction<Void>() {
@Override
public Void run() throws Exception {
checkTokenRenewal(owner, owner);
return null;
}
});
}
@Test
public void testTokenRenewalWrongUser() throws Exception {
try {
owner.doAs(new PrivilegedExceptionAction<Void>() {
@Override
public Void run() throws Exception {
checkTokenRenewal(owner, other);
return null;
}
});
} catch (YarnRemoteException e) {
Assert.assertEquals(e.getMessage(),
"Client " + owner.getUserName() +
" tries to renew a token with renewer specified as " +
other.getUserName());
return;
}
Assert.fail("renew should have failed");
}
@Test
public void testTokenRenewalByLoginUser() throws Exception {
UserGroupInformation.getLoginUser().doAs(new PrivilegedExceptionAction<Void>() {
@Override
public Void run() throws Exception {
checkTokenRenewal(owner, owner);
checkTokenRenewal(owner, other);
return null;
}
});
}
private void checkTokenRenewal(UserGroupInformation owner,
UserGroupInformation renewer) throws IOException {
RMDelegationTokenIdentifier tokenIdentifier =
new RMDelegationTokenIdentifier(
new Text(owner.getUserName()), new Text(renewer.getUserName()), null);
Token<?> token =
new Token<RMDelegationTokenIdentifier>(tokenIdentifier, dtsm);
DelegationToken dToken = BuilderUtils.newDelegationToken(
token.getIdentifier(), token.getKind().toString(),
token.getPassword(), token.getService().toString());
RenewDelegationTokenRequest request =
Records.newRecord(RenewDelegationTokenRequest.class);
request.setDelegationToken(dToken);
RMContext rmContext = mock(RMContext.class);
ClientRMService rmService = new ClientRMService(
rmContext, null, null, null, dtsm);
rmService.renewDelegationToken(request);
}
private void mockRMContext(YarnScheduler yarnScheduler, RMContext rmContext) private void mockRMContext(YarnScheduler yarnScheduler, RMContext rmContext)
throws IOException { throws IOException {
Dispatcher dispatcher = mock(Dispatcher.class); Dispatcher dispatcher = mock(Dispatcher.class);