Author: vinodkv
Date: Wed Jul 2 21:36:42 2014
New Revision: 1607484
URL: http://svn.apache.org/r1607484
Log:
YARN-2232. Fixed ResourceManager to allow DelegationToken owners to be able to
cancel their own tokens in secure mode. Contributed by Varun Vasudev.
Modified:
hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt
hadoop/common/trunk/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/trunk/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/trunk/hadoop-yarn-project/CHANGES.txt
URL:
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt?rev=1607484&r1=1607483&r2=1607484&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt (original)
+++ hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt Wed Jul 2 21:36:42 2014
@@ -328,6 +328,9 @@ Release 2.5.0 - UNRELEASED
YARN-2216 YARN-2065 AM cannot create new containers after restart
(Jian He via stevel)
+ YARN-2232. Fixed ResourceManager to allow DelegationToken owners to be able
+ to cancel their own tokens in secure mode. (Varun Vasudev via vinodkv)
+
Release 2.4.1 - 2014-06-23
INCOMPATIBLE CHANGES
Modified:
hadoop/common/trunk/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/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java?rev=1607484&r1=1607483&r2=1607484&view=diff
==============================================================================
---
hadoop/common/trunk/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/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java
Wed Jul 2 21:36:42 2014
@@ -919,7 +919,7 @@ public class ClientRMService extends Abs
protoToken.getIdentifier().array(), protoToken.getPassword().array(),
new Text(protoToken.getKind()), new Text(protoToken.getService()));
- String user = getRenewerForToken(token);
+ String user = UserGroupInformation.getCurrentUser().getUserName();
rmDTSecretManager.cancelToken(token, user);
return Records.newRecord(CancelDelegationTokenResponse.class);
} catch (IOException e) {
Modified:
hadoop/common/trunk/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/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java?rev=1607484&r1=1607483&r2=1607484&view=diff
==============================================================================
---
hadoop/common/trunk/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/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java
Wed Jul 2 21:36:42 2014
@@ -44,16 +44,17 @@ import java.util.concurrent.ConcurrentHa
import java.util.concurrent.CyclicBarrier;
import org.junit.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.authentication.util.KerberosName;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.yarn.MockApps;
import org.apache.hadoop.yarn.api.ApplicationClientProtocol;
import org.apache.hadoop.yarn.api.protocolrecords.ApplicationsRequestScope;
+import org.apache.hadoop.yarn.api.protocolrecords.CancelDelegationTokenRequest;
import
org.apache.hadoop.yarn.api.protocolrecords.GetApplicationAttemptReportRequest;
import
org.apache.hadoop.yarn.api.protocolrecords.GetApplicationAttemptReportResponse;
import
org.apache.hadoop.yarn.api.protocolrecords.GetApplicationAttemptsRequest;
@@ -138,6 +139,10 @@ public class TestClientRMService {
private final static String QUEUE_1 = "Q-1";
private final static String QUEUE_2 = "Q-2";
+ private final static String kerberosRule =
"RULE:[1:$1@$0](.*@EXAMPLE.COM)s/@.*//\nDEFAULT";
+ static {
+ KerberosName.setRules(kerberosRule);
+ }
@BeforeClass
public static void setupSecretManager() throws IOException {
@@ -479,6 +484,17 @@ public class TestClientRMService {
UserGroupInformation.createRemoteUser("owner");
private static final UserGroupInformation other =
UserGroupInformation.createRemoteUser("other");
+ private static final UserGroupInformation tester =
+ UserGroupInformation.createRemoteUser("tester");
+ private static final String testerPrincipal = "[email protected]";
+ private static final String ownerPrincipal = "[email protected]";
+ private static final String otherPrincipal = "[email protected]";
+ private static final UserGroupInformation testerKerb =
+ UserGroupInformation.createRemoteUser(testerPrincipal);
+ private static final UserGroupInformation ownerKerb =
+ UserGroupInformation.createRemoteUser(ownerPrincipal);
+ private static final UserGroupInformation otherKerb =
+ UserGroupInformation.createRemoteUser(otherPrincipal);
@Test
public void testTokenRenewalByOwner() throws Exception {
@@ -546,6 +562,147 @@ public class TestClientRMService {
rmService.renewDelegationToken(request);
}
+ @Test
+ public void testTokenCancellationByOwner() throws Exception {
+ // two tests required - one with a kerberos name
+ // and with a short name
+ RMContext rmContext = mock(RMContext.class);
+ final ClientRMService rmService =
+ new ClientRMService(rmContext, null, null, null, null, dtsm);
+ testerKerb.doAs(new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws Exception {
+ checkTokenCancellation(rmService, testerKerb, other);
+ return null;
+ }
+ });
+ owner.doAs(new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws Exception {
+ checkTokenCancellation(owner, other);
+ return null;
+ }
+ });
+ }
+
+ @Test
+ public void testTokenCancellationByRenewer() throws Exception {
+ // two tests required - one with a kerberos name
+ // and with a short name
+ RMContext rmContext = mock(RMContext.class);
+ final ClientRMService rmService =
+ new ClientRMService(rmContext, null, null, null, null, dtsm);
+ testerKerb.doAs(new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws Exception {
+ checkTokenCancellation(rmService, owner, testerKerb);
+ return null;
+ }
+ });
+ other.doAs(new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws Exception {
+ checkTokenCancellation(owner, other);
+ return null;
+ }
+ });
+ }
+
+ @Test
+ public void testTokenCancellationByWrongUser() {
+ // two sets to test -
+ // 1. try to cancel tokens of short and kerberos users as a kerberos UGI
+ // 2. try to cancel tokens of short and kerberos users as a simple auth UGI
+
+ RMContext rmContext = mock(RMContext.class);
+ final ClientRMService rmService =
+ new ClientRMService(rmContext, null, null, null, null, dtsm);
+ UserGroupInformation[] kerbTestOwners =
+ { owner, other, tester, ownerKerb, otherKerb };
+ UserGroupInformation[] kerbTestRenewers =
+ { owner, other, ownerKerb, otherKerb };
+ for (final UserGroupInformation tokOwner : kerbTestOwners) {
+ for (final UserGroupInformation tokRenewer : kerbTestRenewers) {
+ try {
+ testerKerb.doAs(new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws Exception {
+ try {
+ checkTokenCancellation(rmService, tokOwner, tokRenewer);
+ Assert.fail("We should not reach here; token owner = "
+ + tokOwner.getUserName() + ", renewer = "
+ + tokRenewer.getUserName());
+ return null;
+ } catch (YarnException e) {
+ Assert.assertTrue(e.getMessage().contains(
+ testerKerb.getUserName()
+ + " is not authorized to cancel the token"));
+ return null;
+ }
+ }
+ });
+ } catch (Exception e) {
+ Assert.fail("Unexpected exception; " + e.getMessage());
+ }
+ }
+ }
+
+ UserGroupInformation[] simpleTestOwners =
+ { owner, other, ownerKerb, otherKerb, testerKerb };
+ UserGroupInformation[] simpleTestRenewers =
+ { owner, other, ownerKerb, otherKerb };
+ for (final UserGroupInformation tokOwner : simpleTestOwners) {
+ for (final UserGroupInformation tokRenewer : simpleTestRenewers) {
+ try {
+ tester.doAs(new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws Exception {
+ try {
+ checkTokenCancellation(tokOwner, tokRenewer);
+ Assert.fail("We should not reach here; token owner = "
+ + tokOwner.getUserName() + ", renewer = "
+ + tokRenewer.getUserName());
+ return null;
+ } catch (YarnException ex) {
+ Assert.assertTrue(ex.getMessage().contains(
+ tester.getUserName()
+ + " is not authorized to cancel the token"));
+ return null;
+ }
+ }
+ });
+ } catch (Exception e) {
+ Assert.fail("Unexpected exception; " + e.getMessage());
+ }
+ }
+ }
+ }
+
+ private void checkTokenCancellation(UserGroupInformation owner,
+ UserGroupInformation renewer) throws IOException, YarnException {
+ RMContext rmContext = mock(RMContext.class);
+ final ClientRMService rmService =
+ new ClientRMService(rmContext, null, null, null, null, dtsm);
+ checkTokenCancellation(rmService, owner, renewer);
+ }
+
+ private void checkTokenCancellation(ClientRMService rmService,
+ UserGroupInformation owner, UserGroupInformation renewer)
+ throws IOException, YarnException {
+ RMDelegationTokenIdentifier tokenIdentifier =
+ new RMDelegationTokenIdentifier(new Text(owner.getUserName()),
+ new Text(renewer.getUserName()), null);
+ Token<?> token =
+ new Token<RMDelegationTokenIdentifier>(tokenIdentifier, dtsm);
+ org.apache.hadoop.yarn.api.records.Token dToken =
+ BuilderUtils.newDelegationToken(token.getIdentifier(), token.getKind()
+ .toString(), token.getPassword(), token.getService().toString());
+ CancelDelegationTokenRequest request =
+ Records.newRecord(CancelDelegationTokenRequest.class);
+ request.setDelegationToken(dToken);
+ rmService.cancelDelegationToken(request);
+ }
+
@Test (timeout = 30000)
@SuppressWarnings ("rawtypes")
public void testAppSubmit() throws Exception {