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 7593b4e57dd..67c4aa26db3 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 @@ -317,8 +317,9 @@ public synchronized void addPersistedDelegationToken( int keyId = identifier.getMasterKeyId(); DelegationKey dKey = allKeys.get(keyId); if (dKey == null) { - LOG.warn("No KEY found for persisted identifier " + LOG.warn("No KEY found for persisted identifier, removing stored token " + formatTokenId(identifier)); + removeStoredToken(identifier); return; } byte[] password = createPassword(identifier.getBytes(), dKey.getKey()); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/security/TestRMDelegationTokens.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/security/TestRMDelegationTokens.java index 2c52377995a..918b80db302 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/security/TestRMDelegationTokens.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/security/TestRMDelegationTokens.java @@ -33,6 +33,7 @@ import org.apache.hadoop.security.token.Token; import org.apache.hadoop.security.token.delegation.DelegationKey; import org.apache.hadoop.util.ExitUtil; +import org.apache.hadoop.util.Time; import org.apache.hadoop.yarn.api.protocolrecords.GetDelegationTokenRequest; import org.apache.hadoop.yarn.api.protocolrecords.GetDelegationTokenResponse; import org.apache.hadoop.yarn.conf.YarnConfiguration; @@ -164,6 +165,53 @@ public void testRemoveExpiredMasterKeyInRMStateStore() throws Exception { rm1.stop(); } + // Test removing token without key from state-store. + @Test(timeout = 45000) + public void testUnknownKeyTokensOnRecover() throws Exception { + int masterID = 1234; + int sequenceNumber = 1000; + + MemoryRMStateStore memStore = new MockMemoryRMStateStore(); + memStore.init(testConf); + // Need RM to get the secret manager and call recover + MockRM rm1 = new MyMockRM(testConf, memStore); + rm1.start(); + RMDelegationTokenSecretManager dtSecretManager = + rm1.getRMContext().getRMDelegationTokenSecretManager(); + // short cut to generate a basic token with unknown key + RMDelegationTokenIdentifier rmDT = new RMDelegationTokenIdentifier( + new Text("owner"), new Text("renewer"), new Text("realuser")); + // set a master key which is not used + rmDT.setMasterKeyId(masterID); + rmDT.setSequenceNumber(sequenceNumber); + long tokenTime = Time.now() + 60000; + rmDT.setMaxDate(tokenTime); + dtSecretManager.storeNewToken(rmDT, tokenTime); + // give it time to process + Thread.sleep(500); + RMState rmState = memStore.getState(); + Assert.assertEquals("One token should have been stored", 1, + rmState.getRMDTSecretManagerState().getTokenState().size()); + Assert.assertTrue("Token should be in secret manager but is not", + rmState.getRMDTSecretManagerState().getTokenState().containsKey(rmDT)); + // Cannot recover while running: stop and clear + dtSecretManager.stopThreads(); + dtSecretManager.reset(); + Assert.assertFalse("Token should not be in secret manager but is found", + dtSecretManager.getAllTokens().containsKey(rmDT)); + dtSecretManager.recover(rmState); + Assert.assertEquals("Token should not have been restored", 0, + rmState.getRMDTSecretManagerState().getTokenState().size()); + Assert.assertFalse("Token should not be in secret manager but is found", + rmState.getRMDTSecretManagerState().getTokenState().containsKey(rmDT)); + dtSecretManager.startThreads(); + // sanity check that things are working + dtSecretManager.storeNewToken(rmDT, Time.now()); + Assert.assertTrue("Token should be in secret manager but is not", + rmState.getRMDTSecretManagerState().getTokenState().containsKey(rmDT)); + rm1.stop(); + } + class MyMockRM extends TestSecurityMockRM { public MyMockRM(Configuration conf, RMStateStore store) {