From f4d4d3474cfd2d1f2d243f5ae5cec17af38270b1 Mon Sep 17 00:00:00 2001 From: Xiao Chen Date: Mon, 22 Aug 2016 14:31:13 -0700 Subject: [PATCH] HADOOP-13487. Hadoop KMS should load old delegation tokens from Zookeeper on startup. Contributed by Xiao Chen. --- .../ZKDelegationTokenSecretManager.java | 44 +++++++++ .../TestZKDelegationTokenSecretManager.java | 93 ++++++++++++++++++- 2 files changed, 136 insertions(+), 1 deletion(-) 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 c3ad9f35cdd..6c66e989362 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 @@ -361,6 +361,7 @@ public abstract class ZKDelegationTokenSecretManager children; + if (isTokenCache) { + children = tokenCache.getCurrentData(); + } else { + children = keyCache.getCurrentData(); + } + + int count = 0; + for (ChildData child : children) { + try { + if (isTokenCache) { + processTokenAddOrUpdate(child); + } else { + processKeyAddOrUpdate(child.getData()); + } + } catch (Exception e) { + LOG.info("Ignoring node {} because it failed to load.", + child.getPath()); + LOG.debug("Failure exception:", e); + ++count; + } + } + if (count > 0) { + LOG.warn("Ignored {} nodes while loading {} cache.", count, cacheName); + } + LOG.info("Loaded {} cache.", cacheName); + } + private void processKeyAddOrUpdate(byte[] data) throws IOException { ByteArrayInputStream bin = new ByteArrayInputStream(data); DataInputStream din = new DataInputStream(bin); @@ -890,4 +929,9 @@ public abstract class ZKDelegationTokenSecretManager token = + (Token) tm + .createToken(UserGroupInformation.getCurrentUser(), "good"); + Assert.assertNotNull(token); + Token cancelled = + (Token) tm + .createToken(UserGroupInformation.getCurrentUser(), "cancelled"); + Assert.assertNotNull(cancelled); + tm.verifyToken(token); + tm.verifyToken(cancelled); + + // Cancel one token, verify it's gone + tm.cancelToken(cancelled, "cancelled"); + final AbstractDelegationTokenSecretManager sm = + tm.getDelegationTokenSecretManager(); + final ZKDelegationTokenSecretManager zksm = + (ZKDelegationTokenSecretManager) sm; + final AbstractDelegationTokenIdentifier idCancelled = + sm.decodeTokenIdentifier(cancelled); + LOG.info("Waiting for the cancelled token to be removed"); + + GenericTestUtils.waitFor(new Supplier() { + @Override + public Boolean get() { + AbstractDelegationTokenSecretManager.DelegationTokenInformation dtinfo = + zksm.getTokenInfo(idCancelled); + return dtinfo == null; + } + }, 100, 5000); + + // Fake a restart which launches a new tm + tm.destroy(); + tm = new DelegationTokenManager(conf, new Text("bla")); + tm.init(); + final AbstractDelegationTokenSecretManager smNew = + tm.getDelegationTokenSecretManager(); + final ZKDelegationTokenSecretManager zksmNew = + (ZKDelegationTokenSecretManager) smNew; + + // The cancelled token should be gone, and not loaded. + AbstractDelegationTokenIdentifier id = + smNew.decodeTokenIdentifier(cancelled); + AbstractDelegationTokenSecretManager.DelegationTokenInformation dtinfo = + zksmNew.getTokenInfo(id); + Assert.assertNull("canceled dt should be gone!", dtinfo); + + // The good token should be loaded on startup, and removed after expiry. + id = smNew.decodeTokenIdentifier(token); + dtinfo = zksmNew.getTokenInfoFromMemory(id); + Assert.assertNotNull("good dt should be in memory!", dtinfo); + + // Wait for the good token to expire. + Thread.sleep(5000); + final ZKDelegationTokenSecretManager zksm1 = zksmNew; + final AbstractDelegationTokenIdentifier id1 = id; + GenericTestUtils.waitFor(new Supplier() { + @Override + public Boolean get() { + LOG.info("Waiting for the expired token to be removed..."); + return zksm1.getTokenInfo(id1) == null; + } + }, 1000, 5000); + } }