You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by vi...@apache.org on 2014/10/26 19:29:34 UTC

[1/2] git commit: HADOOP-11170. ZKDelegationTokenSecretManager fails to renewToken created by a peer. (Arun Suresh and Gregory Chanan via kasha)

Repository: hadoop
Updated Branches:
  refs/heads/branch-2.6 cccfc27e0 -> 259db7a72


HADOOP-11170. ZKDelegationTokenSecretManager fails to renewToken created by a peer. (Arun Suresh and Gregory Chanan via kasha)

(cherry picked from commit db45f047ab6b19d8a3e7752bb2cde10827cd8dad)

Conflicts:
	hadoop-common-project/hadoop-common/CHANGES.txt


Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/7bb5071a
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/7bb5071a
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/7bb5071a

Branch: refs/heads/branch-2.6
Commit: 7bb5071a9e5a6fe1330bd61aef316f1c5b2da7de
Parents: cccfc27
Author: Karthik Kambatla <ka...@apache.org>
Authored: Thu Oct 23 17:04:14 2014 -0700
Committer: Vinod Kumar Vavilapalli <vi...@apache.org>
Committed: Sun Oct 26 11:28:50 2014 -0700

----------------------------------------------------------------------
 hadoop-common-project/hadoop-common/CHANGES.txt |   3 +
 .../AbstractDelegationTokenSecretManager.java   |  44 +++++--
 .../ZKDelegationTokenSecretManager.java         |  86 ++++++++----
 .../TestZKDelegationTokenSecretManager.java     | 131 +++++++++++++++----
 4 files changed, 205 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/7bb5071a/hadoop-common-project/hadoop-common/CHANGES.txt
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt
index e5a25fd..a7194e3 100644
--- a/hadoop-common-project/hadoop-common/CHANGES.txt
+++ b/hadoop-common-project/hadoop-common/CHANGES.txt
@@ -636,6 +636,9 @@ Release 2.6.0 - UNRELEASED
     HADOOP-11228. Winutils task: unsecure path should not call
     AddNodeManagerAndUserACEsToObject. (Remus Rusanu via jianhe)
 
+    HADOOP-11170. ZKDelegationTokenSecretManager fails to renewToken created by 
+    a peer. (Arun Suresh and Gregory Chanan via kasha)
+
 Release 2.5.1 - 2014-09-05
 
   INCOMPATIBLE CHANGES

http://git-wip-us.apache.org/repos/asf/hadoop/blob/7bb5071a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java
index ebba6a1..ac399ec 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java
@@ -20,10 +20,13 @@ package org.apache.hadoop.security.token.delegation;
 
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.io.MD5Hash;
 import org.apache.hadoop.io.Text;
 
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
+import java.io.DataOutputStream;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -125,7 +128,7 @@ extends AbstractDelegationTokenIdentifier>
    * Reset all data structures and mutable state.
    */
   public synchronized void reset() {
-    currentId = 0;
+    setCurrentKeyId(0);
     allKeys.clear();
     setDelegationTokenSeqNum(0);
     currentTokens.clear();
@@ -138,8 +141,8 @@ extends AbstractDelegationTokenIdentifier>
   public synchronized void addKey(DelegationKey key) throws IOException {
     if (running) // a safety check
       throw new IOException("Can't add delegation key to a running SecretManager.");
-    if (key.getKeyId() > currentId) {
-      currentId = key.getKeyId();
+    if (key.getKeyId() > getCurrentKeyId()) {
+      setCurrentKeyId(key.getKeyId());
     }
     allKeys.put(key.getKeyId(), key);
   }
@@ -186,6 +189,30 @@ extends AbstractDelegationTokenIdentifier>
    * For subclasses externalizing the storage, for example Zookeeper
    * based implementations
    */
+  protected synchronized int getCurrentKeyId() {
+    return currentId;
+  }
+
+  /**
+   * For subclasses externalizing the storage, for example Zookeeper
+   * based implementations
+   */
+  protected synchronized int incrementCurrentKeyId() {
+    return ++currentId;
+  }
+
+  /**
+   * For subclasses externalizing the storage, for example Zookeeper
+   * based implementations
+   */
+  protected synchronized void setCurrentKeyId(int keyId) {
+    currentId = keyId;
+  }
+
+  /**
+   * For subclasses externalizing the storage, for example Zookeeper
+   * based implementations
+   */
   protected synchronized int getDelegationTokenSeqNum() {
     return delegationTokenSequenceNumber;
   }
@@ -282,8 +309,8 @@ extends AbstractDelegationTokenIdentifier>
       return;
     }
     byte[] password = createPassword(identifier.getBytes(), dKey.getKey());
-    if (identifier.getSequenceNumber() > delegationTokenSequenceNumber) {
-      delegationTokenSequenceNumber = identifier.getSequenceNumber();
+    if (identifier.getSequenceNumber() > getDelegationTokenSeqNum()) {
+      setDelegationTokenSeqNum(identifier.getSequenceNumber());
     }
     if (getTokenInfo(identifier) == null) {
       currentTokens.put(identifier, new DelegationTokenInformation(renewDate,
@@ -303,7 +330,7 @@ extends AbstractDelegationTokenIdentifier>
     /* Create a new currentKey with an estimated expiry date. */
     int newCurrentId;
     synchronized (this) {
-      newCurrentId = currentId+1;
+      newCurrentId = incrementCurrentKeyId();
     }
     DelegationKey newKey = new DelegationKey(newCurrentId, System
         .currentTimeMillis()
@@ -311,7 +338,6 @@ extends AbstractDelegationTokenIdentifier>
     //Log must be invoked outside the lock on 'this'
     logUpdateMasterKey(newKey);
     synchronized (this) {
-      currentId = newKey.getKeyId();
       currentKey = newKey;
       storeDelegationKey(currentKey);
     }
@@ -358,9 +384,9 @@ extends AbstractDelegationTokenIdentifier>
     sequenceNum = incrementDelegationTokenSeqNum();
     identifier.setIssueDate(now);
     identifier.setMaxDate(now + tokenMaxLifetime);
-    identifier.setMasterKeyId(currentId);
+    identifier.setMasterKeyId(currentKey.getKeyId());
     identifier.setSequenceNumber(sequenceNum);
-    LOG.info("Creating password for identifier: " + identifier);
+    LOG.info("Creating password for identifier: [" + MD5Hash.digest(identifier.getBytes()) + ", " + currentKey.getKeyId() + "]");
     byte[] password = createPassword(identifier.getBytes(), currentKey.getKey());
     DelegationTokenInformation tokenInfo = new DelegationTokenInformation(now
         + tokenRenewInterval, password, getTrackingIdIfEnabled(identifier));

http://git-wip-us.apache.org/repos/asf/hadoop/blob/7bb5071a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/ZKDelegationTokenSecretManager.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/ZKDelegationTokenSecretManager.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/ZKDelegationTokenSecretManager.java
index 5f68844..82dd2da 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/ZKDelegationTokenSecretManager.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/ZKDelegationTokenSecretManager.java
@@ -48,7 +48,6 @@ import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.classification.InterfaceAudience.Private;
 import org.apache.hadoop.classification.InterfaceStability.Unstable;
 import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.security.token.SecretManager;
 import org.apache.hadoop.security.token.delegation.web.DelegationTokenManager;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
@@ -56,6 +55,7 @@ import org.apache.zookeeper.ZooDefs.Perms;
 import org.apache.zookeeper.client.ZooKeeperSaslClient;
 import org.apache.zookeeper.data.ACL;
 import org.apache.zookeeper.data.Id;
+import org.apache.zookeeper.data.Stat;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -104,6 +104,7 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
 
   private static final String ZK_DTSM_NAMESPACE = "ZKDTSMRoot";
   private static final String ZK_DTSM_SEQNUM_ROOT = "ZKDTSMSeqNumRoot";
+  private static final String ZK_DTSM_KEYID_ROOT = "ZKDTSMKeyIdRoot";
   private static final String ZK_DTSM_TOKENS_ROOT = "ZKDTSMTokensRoot";
   private static final String ZK_DTSM_MASTER_KEY_ROOT = "ZKDTSMMasterKeyRoot";
 
@@ -119,7 +120,8 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
 
   private final boolean isExternalClient;
   private final CuratorFramework zkClient;
-  private SharedCount seqCounter;
+  private SharedCount delTokSeqCounter;
+  private SharedCount keyIdSeqCounter;
   private PathChildrenCache keyCache;
   private PathChildrenCache tokenCache;
   private ExecutorService listenerThreadPool;
@@ -276,7 +278,7 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
   }
 
   @Override
-  public synchronized void startThreads() throws IOException {
+  public void startThreads() throws IOException {
     if (!isExternalClient) {
       try {
         zkClient.start();
@@ -285,14 +287,22 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
       }
     }
     try {
-      seqCounter = new SharedCount(zkClient, ZK_DTSM_SEQNUM_ROOT, 0);
-      if (seqCounter != null) {
-        seqCounter.start();
+      delTokSeqCounter = new SharedCount(zkClient, ZK_DTSM_SEQNUM_ROOT, 0);
+      if (delTokSeqCounter != null) {
+        delTokSeqCounter.start();
       }
     } catch (Exception e) {
       throw new IOException("Could not start Sequence Counter", e);
     }
     try {
+      keyIdSeqCounter = new SharedCount(zkClient, ZK_DTSM_KEYID_ROOT, 0);
+      if (keyIdSeqCounter != null) {
+        keyIdSeqCounter.start();
+      }
+    } catch (Exception e) {
+      throw new IOException("Could not start KeyId Counter", e);
+    }
+    try {
       createPersistentNode(ZK_DTSM_MASTER_KEY_ROOT);
       createPersistentNode(ZK_DTSM_TOKENS_ROOT);
     } catch (Exception e) {
@@ -402,13 +412,16 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
   }
 
   @Override
-  public synchronized void stopThreads() {
+  public void stopThreads() {
     try {
       if (!isExternalClient && (zkClient != null)) {
         zkClient.close();
       }
-      if (seqCounter != null) {
-        seqCounter.close();
+      if (delTokSeqCounter != null) {
+        delTokSeqCounter.close();
+      }
+      if (keyIdSeqCounter != null) {
+        keyIdSeqCounter.close();
       }
       if (keyCache != null) {
         keyCache.close();
@@ -434,31 +447,47 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
   }
 
   @Override
-  protected synchronized int getDelegationTokenSeqNum() {
-    return seqCounter.getCount();
+  protected int getDelegationTokenSeqNum() {
+    return delTokSeqCounter.getCount();
   }
 
   @Override
-  protected synchronized int incrementDelegationTokenSeqNum() {
+  protected int incrementDelegationTokenSeqNum() {
     try {
-      while (!seqCounter.trySetCount(seqCounter.getCount() + 1)) {
+      while (!delTokSeqCounter.trySetCount(delTokSeqCounter.getCount() + 1)) {
       }
     } catch (Exception e) {
       throw new RuntimeException("Could not increment shared counter !!", e);
     }
-    return seqCounter.getCount();
+    return delTokSeqCounter.getCount();
   }
 
   @Override
-  protected synchronized void setDelegationTokenSeqNum(int seqNum) {
+  protected void setDelegationTokenSeqNum(int seqNum) {
     try {
-      seqCounter.setCount(seqNum);
+      delTokSeqCounter.setCount(seqNum);
     } catch (Exception e) {
       throw new RuntimeException("Could not set shared counter !!", e);
     }
   }
 
   @Override
+  protected int getCurrentKeyId() {
+    return keyIdSeqCounter.getCount();
+  }
+
+  @Override
+  protected int incrementCurrentKeyId() {
+    try {
+      while (!keyIdSeqCounter.trySetCount(keyIdSeqCounter.getCount() + 1)) {
+      }
+    } catch (Exception e) {
+      throw new RuntimeException("Could not increment shared keyId counter !!", e);
+    }
+    return keyIdSeqCounter.getCount();
+  }
+
+  @Override
   protected DelegationKey getDelegationKey(int keyId) {
     // First check if its I already have this key
     DelegationKey key = allKeys.get(keyId);
@@ -518,6 +547,11 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
 
   private DelegationTokenInformation getTokenInfoFromZK(TokenIdent ident)
       throws IOException {
+    return getTokenInfoFromZK(ident, false);
+  }
+
+  private DelegationTokenInformation getTokenInfoFromZK(TokenIdent ident,
+      boolean quiet) throws IOException {
     String nodePath =
         getNodePath(ZK_DTSM_TOKENS_ROOT,
             DELEGATION_TOKEN_PREFIX + ident.getSequenceNumber());
@@ -539,7 +573,9 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
         return tokenInfo;
       }
     } catch (KeeperException.NoNodeException e) {
-      LOG.error("No node in path [" + nodePath + "]");
+      if (!quiet) {
+        LOG.error("No node in path [" + nodePath + "]");
+      }
     } catch (Exception ex) {
       throw new IOException(ex);
     }
@@ -604,7 +640,9 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
     }
     try {
       if (zkClient.checkExists().forPath(nodeRemovePath) != null) {
-        zkClient.delete().forPath(nodeRemovePath);
+        while(zkClient.checkExists().forPath(nodeRemovePath) != null){
+          zkClient.delete().guaranteed().forPath(nodeRemovePath);
+        }
       } else {
         LOG.debug("Attempted to delete a non-existing znode " + nodeRemovePath);
       }
@@ -633,10 +671,10 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
             + ident.getSequenceNumber());
     try {
       if (zkClient.checkExists().forPath(nodeRemovePath) != null) {
+        addOrUpdateToken(ident, tokenInfo, true);
+      } else {
         addOrUpdateToken(ident, tokenInfo, false);
         LOG.debug("Attempted to update a non-existing znode " + nodeRemovePath);
-      } else {
-        addOrUpdateToken(ident, tokenInfo, true);
       }
     } catch (Exception e) {
       throw new RuntimeException("Could not update Stored Token ZKDTSMDelegationToken_"
@@ -656,9 +694,11 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
     }
     try {
       if (zkClient.checkExists().forPath(nodeRemovePath) != null) {
-        LOG.debug("Attempted to remove a non-existing znode " + nodeRemovePath);
+        while(zkClient.checkExists().forPath(nodeRemovePath) != null){
+          zkClient.delete().guaranteed().forPath(nodeRemovePath);
+        }
       } else {
-        zkClient.delete().forPath(nodeRemovePath);
+        LOG.debug("Attempted to remove a non-existing znode " + nodeRemovePath);
       }
     } catch (Exception e) {
       throw new RuntimeException(
@@ -682,7 +722,7 @@ public abstract class ZKDelegationTokenSecretManager<TokenIdent extends Abstract
       tokenOut.writeInt(info.getPassword().length);
       tokenOut.write(info.getPassword());
       if (LOG.isDebugEnabled()) {
-        LOG.debug((isUpdate ? "Storing " : "Updating ")
+        LOG.debug((isUpdate ? "Updating " : "Storing ")
             + "ZKDTSMDelegationToken_" +
             ident.getSequenceNumber());
       }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/7bb5071a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/TestZKDelegationTokenSecretManager.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/TestZKDelegationTokenSecretManager.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/TestZKDelegationTokenSecretManager.java
index eece2de..b3049c4 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/TestZKDelegationTokenSecretManager.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/token/delegation/TestZKDelegationTokenSecretManager.java
@@ -22,50 +22,127 @@ import org.apache.curator.test.TestingServer;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.io.Text;
 import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.token.SecretManager;
 import org.apache.hadoop.security.token.Token;
 import org.apache.hadoop.security.token.delegation.web.DelegationTokenIdentifier;
 import org.apache.hadoop.security.token.delegation.web.DelegationTokenManager;
+import org.junit.After;
 import org.junit.Assert;
+import org.junit.Before;
+
+import static org.junit.Assert.fail;
+
 import org.junit.Test;
 
 public class TestZKDelegationTokenSecretManager {
 
   private static final long DAY_IN_SECS = 86400;
 
+  private TestingServer zkServer;
+
+  @Before
+  public void setup() throws Exception {
+    zkServer = new TestingServer();
+    zkServer.start();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if (zkServer != null) {
+      zkServer.close();
+    }
+  }
+
+  protected Configuration getSecretConf(String connectString) {
+   Configuration conf = new Configuration();
+   conf.setBoolean(DelegationTokenManager.ENABLE_ZK_KEY, true);
+   conf.set(ZKDelegationTokenSecretManager.ZK_DTSM_ZK_CONNECTION_STRING, connectString);
+   conf.set(ZKDelegationTokenSecretManager.ZK_DTSM_ZNODE_WORKING_PATH, "testPath");
+   conf.set(ZKDelegationTokenSecretManager.ZK_DTSM_ZK_AUTH_TYPE, "none");
+   conf.setLong(DelegationTokenManager.UPDATE_INTERVAL, DAY_IN_SECS);
+   conf.setLong(DelegationTokenManager.MAX_LIFETIME, DAY_IN_SECS);
+   conf.setLong(DelegationTokenManager.RENEW_INTERVAL, DAY_IN_SECS);
+   conf.setLong(DelegationTokenManager.REMOVAL_SCAN_INTERVAL, DAY_IN_SECS);
+   return conf;
+  }
+
   @SuppressWarnings("unchecked")
   @Test
-  public void testZKDelTokSecretManager() throws Exception {
-    TestingServer zkServer = new TestingServer();
+  public void testMultiNodeOperations() throws Exception {
     DelegationTokenManager tm1, tm2 = null;
-    zkServer.start();
+    String connectString = zkServer.getConnectString();
+    Configuration conf = getSecretConf(connectString);
+    tm1 = new DelegationTokenManager(conf, new Text("bla"));
+    tm1.init();
+    tm2 = new DelegationTokenManager(conf, new Text("bla"));
+    tm2.init();
+
+    Token<DelegationTokenIdentifier> token =
+        (Token<DelegationTokenIdentifier>) tm1.createToken(
+            UserGroupInformation.getCurrentUser(), "foo");
+    Assert.assertNotNull(token);
+    tm2.verifyToken(token);
+    tm2.renewToken(token, "foo");
+    tm1.verifyToken(token);
+    tm1.cancelToken(token, "foo");
     try {
-      String connectString = zkServer.getConnectString();
-      Configuration conf = new Configuration();
-      conf.setBoolean(DelegationTokenManager.ENABLE_ZK_KEY, true);
-      conf.set(ZKDelegationTokenSecretManager.ZK_DTSM_ZK_CONNECTION_STRING, connectString);
-      conf.set(ZKDelegationTokenSecretManager.ZK_DTSM_ZNODE_WORKING_PATH, "testPath");
-      conf.set(ZKDelegationTokenSecretManager.ZK_DTSM_ZK_AUTH_TYPE, "none");
-      conf.setLong(DelegationTokenManager.UPDATE_INTERVAL, DAY_IN_SECS);
-      conf.setLong(DelegationTokenManager.MAX_LIFETIME, DAY_IN_SECS);
-      conf.setLong(DelegationTokenManager.RENEW_INTERVAL, DAY_IN_SECS);
-      conf.setLong(DelegationTokenManager.REMOVAL_SCAN_INTERVAL, DAY_IN_SECS);
-      tm1 = new DelegationTokenManager(conf, new Text("foo"));
-      tm1.init();
-      tm2 = new DelegationTokenManager(conf, new Text("foo"));
-      tm2.init();
-
-      Token<DelegationTokenIdentifier> token =
-          (Token<DelegationTokenIdentifier>) tm1.createToken(
-              UserGroupInformation.getCurrentUser(), "foo");
-      Assert.assertNotNull(token);
       tm2.verifyToken(token);
+      fail("Expected InvalidToken");
+    } catch (SecretManager.InvalidToken it) {
+      // Ignore
+    }
 
-      token = (Token<DelegationTokenIdentifier>) tm2.createToken(
-          UserGroupInformation.getCurrentUser(), "bar");
-      Assert.assertNotNull(token);
+    token = (Token<DelegationTokenIdentifier>) tm2.createToken(
+        UserGroupInformation.getCurrentUser(), "bar");
+    Assert.assertNotNull(token);
+    tm1.verifyToken(token);
+    tm1.renewToken(token, "bar");
+    tm2.verifyToken(token);
+    tm2.cancelToken(token, "bar");
+    try {
       tm1.verifyToken(token);
-    } finally {
-      zkServer.close();
+      fail("Expected InvalidToken");
+    } catch (SecretManager.InvalidToken it) {
+      // Ignore
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void testRenewTokenSingleManager() throws Exception {
+    DelegationTokenManager tm1 = null;
+    String connectString = zkServer.getConnectString();
+    Configuration conf = getSecretConf(connectString);
+    tm1 = new DelegationTokenManager(conf, new Text("foo"));
+    tm1.init();
+
+    Token<DelegationTokenIdentifier> token =
+        (Token<DelegationTokenIdentifier>)
+        tm1.createToken(UserGroupInformation.getCurrentUser(), "foo");
+    Assert.assertNotNull(token);
+    tm1.renewToken(token, "foo");
+    tm1.verifyToken(token);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void testCancelTokenSingleManager() throws Exception {
+    DelegationTokenManager tm1 = null;
+    String connectString = zkServer.getConnectString();
+    Configuration conf = getSecretConf(connectString);
+    tm1 = new DelegationTokenManager(conf, new Text("foo"));
+    tm1.init();
+
+    Token<DelegationTokenIdentifier> token =
+        (Token<DelegationTokenIdentifier>)
+        tm1.createToken(UserGroupInformation.getCurrentUser(), "foo");
+    Assert.assertNotNull(token);
+    tm1.cancelToken(token, "foo");
+    try {
+      tm1.verifyToken(token);
+      fail("Expected InvalidToken");
+    } catch (SecretManager.InvalidToken it) {
+      it.printStackTrace();
     }
   }
 }


[2/2] git commit: YARN-2743. Fixed a bug in ResourceManager that was causing RMDelegationToken identifiers to be tampered and thus causing app submission failures in secure mode. Contributed by Jian He.

Posted by vi...@apache.org.
YARN-2743. Fixed a bug in ResourceManager that was causing RMDelegationToken identifiers to be tampered and thus causing app submission failures in secure mode. Contributed by Jian He.

(cherry picked from commit 018664550507981297fd9f91e29408e6b7801ea9)


Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/259db7a7
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/259db7a7
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/259db7a7

Branch: refs/heads/branch-2.6
Commit: 259db7a726e2a571a682531d3099f2710a41134a
Parents: 7bb5071
Author: Vinod Kumar Vavilapalli <vi...@apache.org>
Authored: Sun Oct 26 11:14:34 2014 -0700
Committer: Vinod Kumar Vavilapalli <vi...@apache.org>
Committed: Sun Oct 26 11:29:06 2014 -0700

----------------------------------------------------------------------
 .../AbstractDelegationTokenIdentifier.java      |   2 +-
 .../AbstractDelegationTokenSecretManager.java   |  15 +-
 hadoop-yarn-project/CHANGES.txt                 |   4 +
 .../client/YARNDelegationTokenIdentifier.java   | 198 ++++---------------
 .../main/proto/server/yarn_security_token.proto |   3 +-
 .../yarn/security/TestYARNTokenIdentifier.java  |   5 -
 .../hadoop-yarn-server-resourcemanager/pom.xml  |   1 +
 .../recovery/FileSystemRMStateStore.java        |  32 +--
 .../recovery/ZKRMStateStore.java                |  31 +--
 .../RMDelegationTokenIdentifierData.java        |  61 ++++++
 .../yarn_server_resourcemanager_recovery.proto  |   6 +
 .../RMDelegationTokenIdentifierForTest.java     | 156 ++++-----------
 .../recovery/RMStateStoreTestBase.java          |   6 +
 13 files changed, 193 insertions(+), 327 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/259db7a7/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenIdentifier.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenIdentifier.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenIdentifier.java
index 168a77b..5a9d076 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenIdentifier.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenIdentifier.java
@@ -159,7 +159,7 @@ extends TokenIdentifier {
     return masterKeyId;
   }
 
-  static boolean isEqual(Object a, Object b) {
+  protected static boolean isEqual(Object a, Object b) {
     return a == null ? b == null : a.equals(b);
   }
   

http://git-wip-us.apache.org/repos/asf/hadoop/blob/259db7a7/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java
index ac399ec..52e6a01 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java
@@ -18,15 +18,8 @@
 
 package org.apache.hadoop.security.token.delegation;
 
-import org.apache.hadoop.classification.InterfaceAudience;
-import org.apache.hadoop.classification.InterfaceStability;
-import org.apache.hadoop.io.MD5Hash;
-import org.apache.hadoop.io.Text;
-
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
-import java.io.DataOutputStream;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -39,10 +32,13 @@ import javax.crypto.SecretKey;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.io.Text;
 import org.apache.hadoop.security.AccessControlException;
 import org.apache.hadoop.security.HadoopKerberosName;
-import org.apache.hadoop.security.token.Token;
 import org.apache.hadoop.security.token.SecretManager;
+import org.apache.hadoop.security.token.Token;
 import org.apache.hadoop.util.Daemon;
 import org.apache.hadoop.util.Time;
 
@@ -386,7 +382,8 @@ extends AbstractDelegationTokenIdentifier>
     identifier.setMaxDate(now + tokenMaxLifetime);
     identifier.setMasterKeyId(currentKey.getKeyId());
     identifier.setSequenceNumber(sequenceNum);
-    LOG.info("Creating password for identifier: [" + MD5Hash.digest(identifier.getBytes()) + ", " + currentKey.getKeyId() + "]");
+    LOG.info("Creating password for identifier: " + identifier
+        + ", currentKey: " + currentKey.getKeyId());
     byte[] password = createPassword(identifier.getBytes(), currentKey.getKey());
     DelegationTokenInformation tokenInfo = new DelegationTokenInformation(now
         + tokenRenewInterval, password, getTrackingIdIfEnabled(identifier));

http://git-wip-us.apache.org/repos/asf/hadoop/blob/259db7a7/hadoop-yarn-project/CHANGES.txt
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt
index eee45ba..30f87e2 100644
--- a/hadoop-yarn-project/CHANGES.txt
+++ b/hadoop-yarn-project/CHANGES.txt
@@ -574,6 +574,10 @@ Release 2.6.0 - UNRELEASED
     YARN-2715. Fixed ResourceManager to respect common configurations for proxy
     users/groups beyond just the YARN level config. (Zhijie Shen via vinodkv)
 
+    YARN-2743. Fixed a bug in ResourceManager that was causing RMDelegationToken
+    identifiers to be tampered and thus causing app submission failures in
+    secure mode. (Jian He via vinodkv)
+
   BREAKDOWN OF YARN-1051 SUBTASKS AND RELATED JIRAS
 
     YARN-1707. Introduce APIs to add/remove/resize queues in the

http://git-wip-us.apache.org/repos/asf/hadoop/blob/259db7a7/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/client/YARNDelegationTokenIdentifier.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/client/YARNDelegationTokenIdentifier.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/client/YARNDelegationTokenIdentifier.java
index 3c5fa867..7ccb923 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/client/YARNDelegationTokenIdentifier.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/client/YARNDelegationTokenIdentifier.java
@@ -22,193 +22,61 @@ import java.io.DataOutput;
 import java.io.DataOutputStream;
 import java.io.IOException;
 
+import org.apache.hadoop.classification.InterfaceAudience.Private;
 import org.apache.hadoop.io.Text;
-import org.apache.hadoop.security.HadoopKerberosName;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
 import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenIdentifier;
 import org.apache.hadoop.yarn.proto.YarnSecurityTokenProtos.YARNDelegationTokenIdentifierProto;
 
+@Private
 public abstract class YARNDelegationTokenIdentifier extends
     AbstractDelegationTokenIdentifier {
-  
-  YARNDelegationTokenIdentifierProto.Builder builder = 
+
+  YARNDelegationTokenIdentifierProto.Builder builder =
       YARNDelegationTokenIdentifierProto.newBuilder();
 
-  public YARNDelegationTokenIdentifier() {}
+  public YARNDelegationTokenIdentifier() {
+  }
 
   public YARNDelegationTokenIdentifier(Text owner, Text renewer, Text realUser) {
-    setOwner(owner);
-    setRenewer(renewer);
-    setRealUser(realUser);
-  }
-  
-  /**
-   * Get the username encoded in the token identifier
-   * 
-   * @return the username or owner
-   */
-  @Override
-  public UserGroupInformation getUser() {
-    String owner = getOwner() == null ? null : getOwner().toString();
-    String realUser = getRealUser() == null ? null: getRealUser().toString();
-    if ( (owner == null) || (owner.toString().isEmpty())) {
-      return null;
-    }
-    final UserGroupInformation realUgi;
-    final UserGroupInformation ugi;
-    if ((realUser == null) || (realUser.toString().isEmpty())
-        || realUser.equals(owner)) {
-      ugi = realUgi = UserGroupInformation.createRemoteUser(owner.toString());
-    } else {
-      realUgi = UserGroupInformation.createRemoteUser(realUser.toString());
-      ugi = UserGroupInformation.createProxyUser(owner.toString(), realUgi);
-    }
-    realUgi.setAuthenticationMethod(AuthenticationMethod.TOKEN);
-    return ugi;
+    super(owner, renewer, realUser);
   }
 
-  public Text getOwner() {
-    String owner = builder.getOwner();
-    if (owner == null) {
-      return null;
-    } else {
-      return new Text(owner);
-    }
+  public YARNDelegationTokenIdentifier(
+      YARNDelegationTokenIdentifierProto.Builder builder) {
+    this.builder = builder;
   }
 
   @Override
-  public void setOwner(Text owner) {
-    if (builder != null && owner != null) {
-      builder.setOwner(owner.toString());
+  public synchronized void readFields(DataInput in) throws IOException {
+    builder.mergeFrom((DataInputStream) in);
+    if (builder.getOwner() != null) {
+      setOwner(new Text(builder.getOwner()));
     }
-  }
-
-  public Text getRenewer() {
-    String renewer = builder.getRenewer();
-    if (renewer == null) {
-      return null;
-    } else {
-      return new Text(renewer);
+    if (builder.getRenewer() != null) {
+      setRenewer(new Text(builder.getRenewer()));
     }
-  }
-
-  @Override
-  public void setRenewer(Text renewer) {
-    if (builder != null && renewer != null) {
-      HadoopKerberosName renewerKrbName = new HadoopKerberosName(renewer.toString());
-      try {
-        builder.setRenewer(renewerKrbName.getShortName());
-      } catch (IOException e) {
-        throw new RuntimeException(e);
-      }
-    }
-  }
-
-  public Text getRealUser() {
-    String realUser = builder.getRealUser();
-    if (realUser == null) {
-      return null;
-    } else {
-      return new Text(realUser);
+    if (builder.getRealUser() != null) {
+      setRealUser(new Text(builder.getRealUser()));
     }
+    setIssueDate(builder.getIssueDate());
+    setMaxDate(builder.getMaxDate());
+    setSequenceNumber(builder.getSequenceNumber());
+    setMasterKeyId(builder.getMasterKeyId());
   }
 
   @Override
-  public void setRealUser(Text realUser) {
-    if (builder != null && realUser != null) {
-      builder.setRealUser(realUser.toString());
-    }
+  public synchronized void write(DataOutput out) throws IOException {
+    builder.setOwner(getOwner().toString());
+    builder.setRenewer(getRenewer().toString());
+    builder.setRealUser(getRealUser().toString());
+    builder.setIssueDate(getIssueDate());
+    builder.setMaxDate(getMaxDate());
+    builder.setSequenceNumber(getSequenceNumber());
+    builder.setMasterKeyId(getMasterKeyId());
+    builder.build().writeTo((DataOutputStream) out);
   }
 
-  public void setIssueDate(long issueDate) {
-    builder.setIssueDate(issueDate);
-  }
-  
-  public long getIssueDate() {
-    return builder.getIssueDate();
+  public YARNDelegationTokenIdentifierProto getProto() {
+    return builder.build();
   }
-  
-  
-  public void setRenewDate(long renewDate) {
-    builder.setRenewDate(renewDate);
-  }
-  
-  public long getRenewDate() {
-    return builder.getRenewDate();
-  }
-  
-  public void setMaxDate(long maxDate) {
-    builder.setMaxDate(maxDate);
-  }
-  
-  public long getMaxDate() {
-    return builder.getMaxDate();
-  }
-
-  public void setSequenceNumber(int seqNum) {
-    builder.setSequenceNumber(seqNum);
-  }
-  
-  public int getSequenceNumber() {
-    return builder.getSequenceNumber();
-  }
-
-  public void setMasterKeyId(int newId) {
-    builder.setMasterKeyId(newId);
-  }
-
-  public int getMasterKeyId() {
-    return builder.getMasterKeyId();
-  }
-  
-  protected static boolean isEqual(Object a, Object b) {
-    return a == null ? b == null : a.equals(b);
-  }
-  
-  @Override
-  public boolean equals(Object obj) {
-    if (obj == this) {
-      return true;
-    }
-    if (obj instanceof YARNDelegationTokenIdentifier) {
-      YARNDelegationTokenIdentifier that = (YARNDelegationTokenIdentifier) obj;
-      return this.getSequenceNumber() == that.getSequenceNumber() 
-          && this.getIssueDate() == that.getIssueDate() 
-          && this.getMaxDate() == that.getMaxDate()
-          && this.getMasterKeyId() == that.getMasterKeyId()
-          && isEqual(this.getOwner(), that.getOwner()) 
-          && isEqual(this.getRenewer(), that.getRenewer())
-          && isEqual(this.getRealUser(), that.getRealUser());
-    }
-    return false;
-  }
-
-  @Override
-  public int hashCode() {
-    return this.getSequenceNumber();
-  }
-  
-  @Override
-  public void readFields(DataInput in) throws IOException {
-    builder.mergeFrom((DataInputStream) in);
-  }
-  
-  @Override
-  public void write(DataOutput out) throws IOException {
-    builder.build().writeTo((DataOutputStream)out);
-  }
-  
-  @Override
-  public String toString() {
-    StringBuilder buffer = new StringBuilder();
-    buffer
-        .append("owner=" + getOwner() + ", renewer=" + getRenewer() + ", realUser="
-            + getRealUser() + ", issueDate=" + getIssueDate() 
-            + ", maxDate=" + getMaxDate() + ", sequenceNumber=" 
-            + getSequenceNumber() + ", masterKeyId="
-            + getMasterKeyId());
-    return buffer.toString();
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/259db7a7/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/proto/server/yarn_security_token.proto
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/proto/server/yarn_security_token.proto b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/proto/server/yarn_security_token.proto
index 60c7fcc..317032d 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/proto/server/yarn_security_token.proto
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/proto/server/yarn_security_token.proto
@@ -63,7 +63,6 @@ message YARNDelegationTokenIdentifierProto {
   optional int64 issueDate = 4;
   optional int64 maxDate = 5;
   optional int32 sequenceNumber = 6;
-  optional int32 masterKeyId = 7 [default = -1];
-  optional int64 renewDate = 8;
+  optional int32 masterKeyId = 7;
 }
 

http://git-wip-us.apache.org/repos/asf/hadoop/blob/259db7a7/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/security/TestYARNTokenIdentifier.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/security/TestYARNTokenIdentifier.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/security/TestYARNTokenIdentifier.java
index 2e6255a..2052c23 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/security/TestYARNTokenIdentifier.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/security/TestYARNTokenIdentifier.java
@@ -257,7 +257,6 @@ public class TestYARNTokenIdentifier {
     long maxDate = 2;
     int sequenceNumber = 3;
     int masterKeyId = 4;
-    long renewDate = 5;
     
     TimelineDelegationTokenIdentifier token = 
         new TimelineDelegationTokenIdentifier(owner, renewer, realUser);
@@ -265,7 +264,6 @@ public class TestYARNTokenIdentifier {
     token.setMaxDate(maxDate);
     token.setSequenceNumber(sequenceNumber);
     token.setMasterKeyId(masterKeyId);
-    token.setRenewDate(renewDate);
     
     TimelineDelegationTokenIdentifier anotherToken = 
         new TimelineDelegationTokenIdentifier();
@@ -299,9 +297,6 @@ public class TestYARNTokenIdentifier {
     
     Assert.assertEquals("masterKeyId from proto is not the same with original token",
         anotherToken.getMasterKeyId(), masterKeyId);
-    
-    Assert.assertEquals("renewDate from proto is not the same with original token",
-            anotherToken.getRenewDate(), renewDate);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/259db7a7/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml
index 8e4e852..6dd0b85 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml
@@ -279,6 +279,7 @@
               <imports>
                 <param>${basedir}/../../../../hadoop-common-project/hadoop-common/src/main/proto</param>
                 <param>${basedir}/../../hadoop-yarn-api/src/main/proto</param>
+                <param>${basedir}/../../hadoop-yarn-common/src/main/proto/server/</param>
                 <param>${basedir}/../hadoop-yarn-server-common/src/main/proto</param>
                 <param>${basedir}/src/main/proto</param>
               </imports>

http://git-wip-us.apache.org/repos/asf/hadoop/blob/259db7a7/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/FileSystemRMStateStore.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/FileSystemRMStateStore.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/FileSystemRMStateStore.java
index d434e07..2bbc5c2 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/FileSystemRMStateStore.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/FileSystemRMStateStore.java
@@ -47,9 +47,9 @@ import org.apache.hadoop.yarn.api.records.ApplicationId;
 import org.apache.hadoop.yarn.conf.YarnConfiguration;
 import org.apache.hadoop.yarn.proto.YarnServerCommonProtos.VersionProto;
 import org.apache.hadoop.yarn.proto.YarnServerResourceManagerRecoveryProtos.AMRMTokenSecretManagerStateProto;
-import org.apache.hadoop.yarn.proto.YarnServerResourceManagerRecoveryProtos.EpochProto;
 import org.apache.hadoop.yarn.proto.YarnServerResourceManagerRecoveryProtos.ApplicationAttemptStateDataProto;
 import org.apache.hadoop.yarn.proto.YarnServerResourceManagerRecoveryProtos.ApplicationStateDataProto;
+import org.apache.hadoop.yarn.proto.YarnServerResourceManagerRecoveryProtos.EpochProto;
 import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
 import org.apache.hadoop.yarn.server.records.Version;
 import org.apache.hadoop.yarn.server.records.impl.pb.VersionPBImpl;
@@ -57,6 +57,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.AMRMTokenS
 import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.ApplicationAttemptStateData;
 import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.ApplicationStateData;
 import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.Epoch;
+import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.RMDelegationTokenIdentifierData;
 import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.impl.pb.AMRMTokenSecretManagerStatePBImpl;
 import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.impl.pb.ApplicationAttemptStateDataPBImpl;
 import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.impl.pb.ApplicationStateDataPBImpl;
@@ -369,12 +370,24 @@ public class FileSystemRMStateStore extends RMStateStore {
         DelegationKey key = new DelegationKey();
         key.readFields(fsIn);
         rmState.rmSecretManagerState.masterKeyState.add(key);
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Loaded delegation key: keyId=" + key.getKeyId()
+              + ", expirationDate=" + key.getExpiryDate());
+        }
       } else if (childNodeName.startsWith(DELEGATION_TOKEN_PREFIX)) {
-        RMDelegationTokenIdentifier identifier = new RMDelegationTokenIdentifier();
-        identifier.readFields(fsIn);
-        long renewDate = identifier.getRenewDate();
+        RMDelegationTokenIdentifierData identifierData =
+            new RMDelegationTokenIdentifierData();
+        identifierData.readFields(fsIn);
+        RMDelegationTokenIdentifier identifier =
+            identifierData.getTokenIdentifier();
+        long renewDate = identifierData.getRenewDate();
+
         rmState.rmSecretManagerState.delegationTokenState.put(identifier,
           renewDate);
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Loaded RMDelegationTokenIdentifier: " + identifier
+              + " renewDate=" + renewDate);
+        }
       } else {
         LOG.warn("Unknown file for recovering RMDelegationTokenSecretManager");
       }
@@ -503,18 +516,15 @@ public class FileSystemRMStateStore extends RMStateStore {
     Path nodeCreatePath =
         getNodePath(rmDTSecretManagerRoot,
           DELEGATION_TOKEN_PREFIX + identifier.getSequenceNumber());
-    ByteArrayOutputStream os = new ByteArrayOutputStream();
-    DataOutputStream fsOut = new DataOutputStream(os);
-    identifier.setRenewDate(renewDate);
-    identifier.write(fsOut);
+    RMDelegationTokenIdentifierData identifierData =
+        new RMDelegationTokenIdentifierData(identifier, renewDate);
     if (isUpdate) {
       LOG.info("Updating RMDelegationToken_" + identifier.getSequenceNumber());
-      updateFile(nodeCreatePath, os.toByteArray());
+      updateFile(nodeCreatePath, identifierData.toByteArray());
     } else {
       LOG.info("Storing RMDelegationToken_" + identifier.getSequenceNumber());
-      writeFile(nodeCreatePath, os.toByteArray());
+      writeFile(nodeCreatePath, identifierData.toByteArray());
     }
-    fsOut.close();
 
     // store sequence number
     Path latestSequenceNumberPath = getNodePath(rmDTSecretManagerRoot,

http://git-wip-us.apache.org/repos/asf/hadoop/blob/259db7a7/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/ZKRMStateStore.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/ZKRMStateStore.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/ZKRMStateStore.java
index fdbf125..ab048ca 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/ZKRMStateStore.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/ZKRMStateStore.java
@@ -50,13 +50,14 @@ import org.apache.hadoop.yarn.proto.YarnServerResourceManagerRecoveryProtos.Appl
 import org.apache.hadoop.yarn.proto.YarnServerResourceManagerRecoveryProtos.ApplicationStateDataProto;
 import org.apache.hadoop.yarn.proto.YarnServerResourceManagerRecoveryProtos.EpochProto;
 import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
-import org.apache.hadoop.yarn.server.records.impl.pb.VersionPBImpl;
 import org.apache.hadoop.yarn.server.records.Version;
+import org.apache.hadoop.yarn.server.records.impl.pb.VersionPBImpl;
 import org.apache.hadoop.yarn.server.resourcemanager.RMZKUtils;
 import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.AMRMTokenSecretManagerState;
 import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.ApplicationAttemptStateData;
 import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.ApplicationStateData;
 import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.Epoch;
+import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.RMDelegationTokenIdentifierData;
 import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.impl.pb.AMRMTokenSecretManagerStatePBImpl;
 import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.impl.pb.ApplicationAttemptStateDataPBImpl;
 import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.impl.pb.ApplicationStateDataPBImpl;
@@ -488,6 +489,10 @@ public class ZKRMStateStore extends RMStateStore {
           DelegationKey key = new DelegationKey();
           key.readFields(fsIn);
           rmState.rmSecretManagerState.masterKeyState.add(key);
+          if (LOG.isDebugEnabled()) {
+            LOG.debug("Loaded delegation key: keyId=" + key.getKeyId()
+                + ", expirationDate=" + key.getExpiryDate());
+          }
         }
       } finally {
         is.close();
@@ -527,12 +532,18 @@ public class ZKRMStateStore extends RMStateStore {
 
       try {
         if (childNodeName.startsWith(DELEGATION_TOKEN_PREFIX)) {
+          RMDelegationTokenIdentifierData identifierData =
+              new RMDelegationTokenIdentifierData();
+          identifierData.readFields(fsIn);
           RMDelegationTokenIdentifier identifier =
-              new RMDelegationTokenIdentifier();
-          identifier.readFields(fsIn);
-          long renewDate = identifier.getRenewDate();
+              identifierData.getTokenIdentifier();
+          long renewDate = identifierData.getRenewDate();
           rmState.rmSecretManagerState.delegationTokenState.put(identifier,
               renewDate);
+          if (LOG.isDebugEnabled()) {
+            LOG.debug("Loaded RMDelegationTokenIdentifier: " + identifier
+                + " renewDate=" + renewDate);
+          }
         }
       } finally {
         is.close();
@@ -770,23 +781,20 @@ public class ZKRMStateStore extends RMStateStore {
     String nodeCreatePath =
         getNodePath(delegationTokensRootPath, DELEGATION_TOKEN_PREFIX
             + rmDTIdentifier.getSequenceNumber());
-    ByteArrayOutputStream tokenOs = new ByteArrayOutputStream();
-    DataOutputStream tokenOut = new DataOutputStream(tokenOs);
     ByteArrayOutputStream seqOs = new ByteArrayOutputStream();
     DataOutputStream seqOut = new DataOutputStream(seqOs);
-
+    RMDelegationTokenIdentifierData identifierData =
+        new RMDelegationTokenIdentifierData(rmDTIdentifier, renewDate);
     try {
-      rmDTIdentifier.setRenewDate(renewDate);
-      rmDTIdentifier.write(tokenOut);
       if (LOG.isDebugEnabled()) {
         LOG.debug((isUpdate ? "Storing " : "Updating ") + "RMDelegationToken_" +
             rmDTIdentifier.getSequenceNumber());
       }
 
       if (isUpdate) {
-        opList.add(Op.setData(nodeCreatePath, tokenOs.toByteArray(), -1));
+        opList.add(Op.setData(nodeCreatePath, identifierData.toByteArray(), -1));
       } else {
-        opList.add(Op.create(nodeCreatePath, tokenOs.toByteArray(), zkAcl,
+        opList.add(Op.create(nodeCreatePath, identifierData.toByteArray(), zkAcl,
             CreateMode.PERSISTENT));
       }
 
@@ -799,7 +807,6 @@ public class ZKRMStateStore extends RMStateStore {
 
      opList.add(Op.setData(dtSequenceNumberPath, seqOs.toByteArray(), -1));
     } finally {
-      tokenOs.close();
       seqOs.close();
     }
   }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/259db7a7/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/records/RMDelegationTokenIdentifierData.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/records/RMDelegationTokenIdentifierData.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/records/RMDelegationTokenIdentifierData.java
new file mode 100644
index 0000000..97b5c1c
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/records/RMDelegationTokenIdentifierData.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.yarn.server.resourcemanager.recovery.records;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import org.apache.hadoop.yarn.proto.YarnServerResourceManagerRecoveryProtos.RMDelegationTokenIdentifierDataProto;
+import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
+import org.apache.hadoop.yarn.security.client.YARNDelegationTokenIdentifier;
+
+public class RMDelegationTokenIdentifierData {
+  RMDelegationTokenIdentifierDataProto.Builder builder =
+      RMDelegationTokenIdentifierDataProto.newBuilder();
+
+  public RMDelegationTokenIdentifierData() {}
+
+  public RMDelegationTokenIdentifierData(
+      YARNDelegationTokenIdentifier identifier, long renewdate) {
+    builder.setTokenIdentifier(identifier.getProto());
+    builder.setRenewDate(renewdate);
+  }
+
+  public void readFields(DataInput in) throws IOException {
+    builder.mergeFrom((DataInputStream) in);
+  }
+
+  public byte[] toByteArray() throws IOException {
+    return builder.build().toByteArray();
+  }
+
+  public RMDelegationTokenIdentifier getTokenIdentifier() throws IOException {
+    ByteArrayInputStream in =
+        new ByteArrayInputStream(builder.getTokenIdentifier().toByteArray());
+    RMDelegationTokenIdentifier identifer = new RMDelegationTokenIdentifier();
+    identifer.readFields(new DataInputStream(in));
+    return identifer;
+  }
+
+  public long getRenewDate() {
+    return builder.getRenewDate();
+  }
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/259db7a7/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/proto/yarn_server_resourcemanager_recovery.proto
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/proto/yarn_server_resourcemanager_recovery.proto b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/proto/yarn_server_resourcemanager_recovery.proto
index 4d29153..3c8ac34 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/proto/yarn_server_resourcemanager_recovery.proto
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/proto/yarn_server_resourcemanager_recovery.proto
@@ -24,6 +24,7 @@ package hadoop.yarn;
 
 import "yarn_server_common_protos.proto";
 import "yarn_protos.proto";
+import "yarn_security_token.proto";
 
 ////////////////////////////////////////////////////////////////////////
 ////// RM recovery related records /////////////////////////////////////
@@ -91,3 +92,8 @@ message AMRMTokenSecretManagerStateProto {
   optional MasterKeyProto current_master_key = 1;
   optional MasterKeyProto next_master_key = 2;
 }
+
+message RMDelegationTokenIdentifierDataProto {
+  optional YARNDelegationTokenIdentifierProto token_identifier = 1;
+  optional int64 renewDate = 2;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/259db7a7/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/RMDelegationTokenIdentifierForTest.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/RMDelegationTokenIdentifierForTest.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/RMDelegationTokenIdentifierForTest.java
index 5e1baf7..29b4a0f 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/RMDelegationTokenIdentifierForTest.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/RMDelegationTokenIdentifierForTest.java
@@ -20,155 +20,73 @@ package org.apache.hadoop.yarn.server.resourcemanager;
 import java.io.DataInput;
 import java.io.DataInputStream;
 import java.io.DataOutput;
+import java.io.DataOutputStream;
 import java.io.IOException;
 
-import org.apache.commons.io.IOUtils;
 import org.apache.hadoop.io.Text;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
-import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
 import org.apache.hadoop.yarn.proto.YarnSecurityTestClientAMTokenProtos.RMDelegationTokenIdentifierForTestProto;
+import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
 
 public class RMDelegationTokenIdentifierForTest extends
     RMDelegationTokenIdentifier {
 
-  private RMDelegationTokenIdentifierForTestProto proto;
-  private RMDelegationTokenIdentifierForTestProto.Builder builder;
+  private RMDelegationTokenIdentifierForTestProto.Builder builder =
+      RMDelegationTokenIdentifierForTestProto.newBuilder();
   
   public RMDelegationTokenIdentifierForTest() {
   }
   
-  public RMDelegationTokenIdentifierForTest(
-      RMDelegationTokenIdentifier token, String message) {
-    builder = RMDelegationTokenIdentifierForTestProto.newBuilder();
+  public RMDelegationTokenIdentifierForTest(RMDelegationTokenIdentifier token,
+      String message) {
     if (token.getOwner() != null) {
-      builder.setOwner(token.getOwner().toString());
+      setOwner(new Text(token.getOwner()));
     }
     if (token.getRenewer() != null) {
-      builder.setRenewer(token.getRenewer().toString());
+      setRenewer(new Text(token.getRenewer()));
     }
     if (token.getRealUser() != null) {
-      builder.setRealUser(token.getRealUser().toString());
+      setRealUser(new Text(token.getRealUser()));
     }
-    builder.setIssueDate(token.getIssueDate());
-    builder.setMaxDate(token.getMaxDate());
-    builder.setSequenceNumber(token.getSequenceNumber());
-    builder.setMasterKeyId(token.getMasterKeyId());
+    setIssueDate(token.getIssueDate());
+    setMaxDate(token.getMaxDate());
+    setSequenceNumber(token.getSequenceNumber());
+    setMasterKeyId(token.getMasterKeyId());
     builder.setMessage(message);
-    proto = builder.build();
-    builder = null;
   }
   
   @Override
   public void write(DataOutput out) throws IOException {
-    out.write(proto.toByteArray());
+    builder.setOwner(getOwner().toString());
+    builder.setRenewer(getRenewer().toString());
+    builder.setRealUser(getRealUser().toString());
+    builder.setIssueDate(getIssueDate());
+    builder.setMaxDate(getMaxDate());
+    builder.setSequenceNumber(getSequenceNumber());
+    builder.setMasterKeyId(getMasterKeyId());
+    builder.setMessage(getMessage());
+    builder.build().writeTo((DataOutputStream) out);
   }
   
   @Override
   public void readFields(DataInput in) throws IOException {
-    DataInputStream dis = (DataInputStream)in;
-    byte[] buffer = IOUtils.toByteArray(dis);
-    proto = RMDelegationTokenIdentifierForTestProto.parseFrom(buffer);
-  }
-  
-  /**
-   * Get the username encoded in the token identifier
-   * 
-   * @return the username or owner
-   */
-  @Override
-  public UserGroupInformation getUser() {
-    String owner = getOwner().toString();
-    String realUser = getRealUser().toString();
-    if ( (owner == null) || (owner.toString().isEmpty())) {
-      return null;
+    builder.mergeFrom((DataInputStream) in);
+    if (builder.getOwner() != null) {
+      setOwner(new Text(builder.getOwner()));
     }
-    final UserGroupInformation realUgi;
-    final UserGroupInformation ugi;
-    if ((realUser == null) || (realUser.toString().isEmpty())
-        || realUser.equals(owner)) {
-      ugi = realUgi = UserGroupInformation.createRemoteUser(owner.toString());
-    } else {
-      realUgi = UserGroupInformation.createRemoteUser(realUser.toString());
-      ugi = UserGroupInformation.createProxyUser(owner.toString(), realUgi);
+    if (builder.getRenewer() != null) {
+      setRenewer(new Text(builder.getRenewer()));
     }
-    realUgi.setAuthenticationMethod(AuthenticationMethod.TOKEN);
-    return ugi;
-  }
-
-  public Text getOwner() {
-    String owner = proto.getOwner();
-    if (owner == null) {
-      return null;
-    } else {
-      return new Text(owner);
+    if (builder.getRealUser() != null) {
+      setRealUser(new Text(builder.getRealUser()));
     }
-  }
-
-  public Text getRenewer() {
-    String renewer = proto.getRenewer();
-    if (renewer == null) {
-      return null;
-    } else {
-      return new Text(renewer);
-    }
-  }
-  
-  public Text getRealUser() {
-    String realUser = proto.getRealUser();
-    if (realUser == null) {
-      return null;
-    } else {
-      return new Text(realUser);
-    }
-  }
-  
-  public void setIssueDate(long issueDate) {
-    RMDelegationTokenIdentifierForTestProto.Builder builder = 
-        RMDelegationTokenIdentifierForTestProto.newBuilder(proto);
-    builder.setIssueDate(issueDate);
-    proto = builder.build();
-  }
-  
-  public long getIssueDate() {
-    return proto.getIssueDate();
-  }
-  
-  public void setMaxDate(long maxDate) {
-    RMDelegationTokenIdentifierForTestProto.Builder builder = 
-        RMDelegationTokenIdentifierForTestProto.newBuilder(proto);
-    builder.setMaxDate(maxDate);
-    proto = builder.build();
-  }
-  
-  public long getMaxDate() {
-    return proto.getMaxDate();
-  }
-
-  public void setSequenceNumber(int seqNum) {
-    RMDelegationTokenIdentifierForTestProto.Builder builder = 
-        RMDelegationTokenIdentifierForTestProto.newBuilder(proto);
-    builder.setSequenceNumber(seqNum);
-    proto = builder.build();
-  }
-  
-  public int getSequenceNumber() {
-    return proto.getSequenceNumber();
-  }
-
-  public void setMasterKeyId(int newId) {
-    RMDelegationTokenIdentifierForTestProto.Builder builder = 
-        RMDelegationTokenIdentifierForTestProto.newBuilder(proto);
-    builder.setMasterKeyId(newId);
-    proto = builder.build();
-  }
-
-  public int getMasterKeyId() {
-    return proto.getMasterKeyId();
+    setIssueDate(builder.getIssueDate());
+    setMaxDate(builder.getMaxDate());
+    setSequenceNumber(builder.getSequenceNumber());
+    setMasterKeyId(builder.getMasterKeyId());
   }
   
   public String getMessage() {
-    return proto.getMessage();
+    return builder.getMessage();
   }
   
   @Override
@@ -189,10 +107,4 @@ public class RMDelegationTokenIdentifierForTest extends
     }
     return false;
   }
-
-  @Override
-  public int hashCode() {
-    return this.getSequenceNumber();
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/259db7a7/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/RMStateStoreTestBase.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/RMStateStoreTestBase.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/RMStateStoreTestBase.java
index 85022d9..00b60d3 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/RMStateStoreTestBase.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/RMStateStoreTestBase.java
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.spy;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -402,6 +403,7 @@ public class RMStateStoreTestBase extends ClientBaseWithFixes{
     RMDelegationTokenIdentifier dtId1 =
         new RMDelegationTokenIdentifier(new Text("owner1"),
           new Text("renewer1"), new Text("realuser1"));
+    byte[] tokenBeforeStore = dtId1.getBytes();
     Long renewDate1 = new Long(System.currentTimeMillis());
     int sequenceNumber = 1111;
     store.storeRMDelegationTokenAndSequenceNumber(dtId1, renewDate1,
@@ -423,6 +425,10 @@ public class RMStateStoreTestBase extends ClientBaseWithFixes{
     Assert.assertEquals(keySet, secretManagerState.getMasterKeyState());
     Assert.assertEquals(sequenceNumber,
         secretManagerState.getDTSequenceNumber());
+    RMDelegationTokenIdentifier tokenAfterStore =
+        secretManagerState.getTokenState().keySet().iterator().next();
+    Assert.assertTrue(Arrays.equals(tokenBeforeStore,
+      tokenAfterStore.getBytes()));
 
     // update RM delegation token;
     renewDate1 = new Long(System.currentTimeMillis());