Author: sseth Date: Wed Jan 9 19:34:01 2013 New Revision: 1431023 URL: http://svn.apache.org/viewvc?rev=1431023&view=rev Log: merge YARN-320 from trunk. RM should always be able to renew its own tokens. Contributed by Daryn Sharp
Modified: hadoop/common/branches/branch-2/hadoop-yarn-project/CHANGES.txt hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java Modified: hadoop/common/branches/branch-2/hadoop-yarn-project/CHANGES.txt URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-yarn-project/CHANGES.txt?rev=1431023&r1=1431022&r2=1431023&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-yarn-project/CHANGES.txt (original) +++ hadoop/common/branches/branch-2/hadoop-yarn-project/CHANGES.txt Wed Jan 9 19:34:01 2013 @@ -270,6 +270,9 @@ Release 0.23.6 - UNRELEASED YARN-50. Implement renewal / cancellation of Delegation Tokens (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 INCOMPATIBLE CHANGES Modified: hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java?rev=1431023&r1=1431022&r2=1431023&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java (original) +++ hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java Wed Jan 9 19:34:01 2013 @@ -519,7 +519,7 @@ public class ClientRMService extends Abs protoToken.getIdentifier().array(), protoToken.getPassword().array(), new Text(protoToken.getKind()), new Text(protoToken.getService())); - String user = UserGroupInformation.getCurrentUser().getShortUserName(); + String user = getRenewerForToken(token); long nextExpTime = rmDTSecretManager.renewToken(token, user); RenewDelegationTokenResponse renewResponse = Records .newRecord(RenewDelegationTokenResponse.class); @@ -543,7 +543,7 @@ public class ClientRMService extends Abs protoToken.getIdentifier().array(), protoToken.getPassword().array(), new Text(protoToken.getKind()), new Text(protoToken.getService())); - String user = UserGroupInformation.getCurrentUser().getShortUserName(); + String user = getRenewerForToken(token); rmDTSecretManager.cancelToken(token, user); return Records.newRecord(CancelDelegationTokenResponse.class); } catch (IOException e) { @@ -551,6 +551,16 @@ public class ClientRMService extends Abs } } + 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, PolicyProvider policyProvider) { this.server.refreshServiceAcl(configuration, policyProvider); Modified: hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java?rev=1431023&r1=1431022&r2=1431023&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java (original) +++ hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java Wed Jan 9 19:34:01 2013 @@ -25,6 +25,7 @@ import static org.mockito.Matchers.anySt import java.io.IOException; import java.net.InetSocketAddress; +import java.security.PrivilegedExceptionAction; import java.util.List; import java.util.concurrent.ConcurrentHashMap; @@ -33,14 +34,19 @@ import junit.framework.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; 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.protocolrecords.GetApplicationReportRequest; import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportResponse; import org.apache.hadoop.yarn.api.protocolrecords.GetClusterNodesRequest; import org.apache.hadoop.yarn.api.protocolrecords.GetQueueInfoRequest; 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.ApplicationReport; +import org.apache.hadoop.yarn.api.records.DelegationToken; import org.apache.hadoop.yarn.api.records.NodeReport; import org.apache.hadoop.yarn.api.records.QueueInfo; import org.apache.hadoop.yarn.conf.YarnConfiguration; @@ -49,11 +55,16 @@ import org.apache.hadoop.yarn.exceptions import org.apache.hadoop.yarn.factories.RecordFactory; import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider; 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.RMAppImpl; 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.junit.Test; +import org.junit.AfterClass; +import org.junit.BeforeClass; public class TestClientRMService { @@ -63,6 +74,21 @@ public class TestClientRMService { private RecordFactory recordFactory = RecordFactoryProvider .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 public void testGetClusterNodes() throws Exception { MockRM rm = new MockRM() { @@ -141,6 +167,74 @@ public class TestClientRMService { 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) throws IOException { Dispatcher dispatcher = mock(Dispatcher.class);