HADOOP-13838. KMSTokenRenewer should close providers (xiaochen via rkanter)

This commit is contained in:
Robert Kanter 2016-11-28 18:08:09 -08:00
parent d60a60be8a
commit 47ca9e26fb
3 changed files with 113 additions and 38 deletions

View File

@ -173,14 +173,20 @@ public long renew(Token<?> token, Configuration conf) throws IOException {
LOG.debug("Renewing delegation token {}", token); LOG.debug("Renewing delegation token {}", token);
KeyProvider keyProvider = KMSUtil.createKeyProvider(conf, KeyProvider keyProvider = KMSUtil.createKeyProvider(conf,
KeyProviderFactory.KEY_PROVIDER_PATH); KeyProviderFactory.KEY_PROVIDER_PATH);
if (!(keyProvider instanceof try {
KeyProviderDelegationTokenExtension.DelegationTokenExtension)) { if (!(keyProvider instanceof
LOG.warn("keyProvider {} cannot renew dt.", keyProvider == null ? KeyProviderDelegationTokenExtension.DelegationTokenExtension)) {
"null" : keyProvider.getClass()); LOG.warn("keyProvider {} cannot renew dt.", keyProvider == null ?
return 0; "null" : keyProvider.getClass());
return 0;
}
return ((KeyProviderDelegationTokenExtension.DelegationTokenExtension)
keyProvider).renewDelegationToken(token);
} finally {
if (keyProvider != null) {
keyProvider.close();
}
} }
return ((KeyProviderDelegationTokenExtension.DelegationTokenExtension)
keyProvider).renewDelegationToken(token);
} }
@Override @Override
@ -188,14 +194,20 @@ public void cancel(Token<?> token, Configuration conf) throws IOException {
LOG.debug("Canceling delegation token {}", token); LOG.debug("Canceling delegation token {}", token);
KeyProvider keyProvider = KMSUtil.createKeyProvider(conf, KeyProvider keyProvider = KMSUtil.createKeyProvider(conf,
KeyProviderFactory.KEY_PROVIDER_PATH); KeyProviderFactory.KEY_PROVIDER_PATH);
if (!(keyProvider instanceof try {
KeyProviderDelegationTokenExtension.DelegationTokenExtension)) { if (!(keyProvider instanceof
LOG.warn("keyProvider {} cannot cancel dt.", keyProvider == null ? KeyProviderDelegationTokenExtension.DelegationTokenExtension)) {
"null" : keyProvider.getClass()); LOG.warn("keyProvider {} cannot cancel dt.", keyProvider == null ?
return; "null" : keyProvider.getClass());
return;
}
((KeyProviderDelegationTokenExtension.DelegationTokenExtension)
keyProvider).cancelDelegationToken(token);
} finally {
if (keyProvider != null) {
keyProvider.close();
}
} }
((KeyProviderDelegationTokenExtension.DelegationTokenExtension)
keyProvider).cancelDelegationToken(token);
} }
} }
@ -1072,6 +1084,7 @@ public void close() throws IOException {
} finally { } finally {
if (sslFactory != null) { if (sslFactory != null) {
sslFactory.destroy(); sslFactory.destroy();
sslFactory = null;
} }
} }
} }

View File

@ -17,6 +17,7 @@
*/ */
package org.apache.hadoop.crypto.key.kms.server; package org.apache.hadoop.crypto.key.kms.server;
import com.google.common.base.Supplier;
import org.apache.curator.test.TestingServer; import org.apache.curator.test.TestingServer;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.crypto.key.KeyProviderFactory; import org.apache.hadoop.crypto.key.KeyProviderFactory;
@ -74,12 +75,16 @@
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
public class TestKMS { public class TestKMS {
private static final Logger LOG = LoggerFactory.getLogger(TestKMS.class); private static final Logger LOG = LoggerFactory.getLogger(TestKMS.class);
private static final String SSL_RELOADER_THREAD_NAME =
"Truststore reloader thread";
@Rule @Rule
public final Timeout testTimeout = new Timeout(180000); public final Timeout testTimeout = new Timeout(180000);
@ -348,7 +353,7 @@ public Void call() throws Exception {
Thread reloaderThread = null; Thread reloaderThread = null;
for (Thread thread : threads) { for (Thread thread : threads) {
if ((thread.getName() != null) if ((thread.getName() != null)
&& (thread.getName().contains("Truststore reloader thread"))) { && (thread.getName().contains(SSL_RELOADER_THREAD_NAME))) {
reloaderThread = thread; reloaderThread = thread;
} }
} }
@ -378,6 +383,7 @@ public Void run() throws Exception {
.addDelegationTokens("myuser", new Credentials()); .addDelegationTokens("myuser", new Credentials());
Assert.assertEquals(1, tokens.length); Assert.assertEquals(1, tokens.length);
Assert.assertEquals("kms-dt", tokens[0].getKind().toString()); Assert.assertEquals("kms-dt", tokens[0].getKind().toString());
kp.close();
return null; return null;
} }
}); });
@ -393,6 +399,7 @@ public Void run() throws Exception {
.addDelegationTokens("myuser", new Credentials()); .addDelegationTokens("myuser", new Credentials());
Assert.assertEquals(1, tokens.length); Assert.assertEquals(1, tokens.length);
Assert.assertEquals("kms-dt", tokens[0].getKind().toString()); Assert.assertEquals("kms-dt", tokens[0].getKind().toString());
kp.close();
} }
return null; return null;
} }
@ -1755,34 +1762,63 @@ public Void run() throws Exception {
}); });
} }
@Test private Configuration setupConfForKerberos(File confDir) throws Exception {
public void testDelegationTokensOpsSimple() throws Exception { final Configuration conf = createBaseKMSConf(confDir, null);
final Configuration conf = new Configuration();
testDelegationTokensOps(conf, false);
}
@Test
public void testDelegationTokensOpsKerberized() throws Exception {
final Configuration conf = new Configuration();
conf.set("hadoop.security.authentication", "kerberos"); conf.set("hadoop.security.authentication", "kerberos");
testDelegationTokensOps(conf, true); conf.set("hadoop.kms.authentication.type", "kerberos");
conf.set("hadoop.kms.authentication.kerberos.keytab",
keytab.getAbsolutePath());
conf.set("hadoop.kms.authentication.kerberos.principal",
"HTTP/localhost");
conf.set("hadoop.kms.authentication.kerberos.name.rules", "DEFAULT");
return conf;
} }
private void testDelegationTokensOps(Configuration conf, @Test
final boolean useKrb) throws Exception { public void testDelegationTokensOpsHttpPseudo() throws Exception {
File confDir = getTestDir(); testDelegationTokensOps(false, false);
conf = createBaseKMSConf(confDir, conf); }
if (useKrb) {
conf.set("hadoop.kms.authentication.type", "kerberos"); @Test
conf.set("hadoop.kms.authentication.kerberos.keytab", public void testDelegationTokensOpsHttpKerberized() throws Exception {
keytab.getAbsolutePath()); testDelegationTokensOps(false, true);
conf.set("hadoop.kms.authentication.kerberos.principal", }
"HTTP/localhost");
conf.set("hadoop.kms.authentication.kerberos.name.rules", "DEFAULT"); @Test
public void testDelegationTokensOpsHttpsPseudo() throws Exception {
testDelegationTokensOps(true, false);
}
@Test
public void testDelegationTokensOpsHttpsKerberized() throws Exception {
testDelegationTokensOps(true, true);
}
private void testDelegationTokensOps(final boolean ssl, final boolean kerb)
throws Exception {
final File confDir = getTestDir();
final Configuration conf;
if (kerb) {
conf = setupConfForKerberos(confDir);
} else {
conf = createBaseKMSConf(confDir, null);
}
final String keystore;
final String password;
if (ssl) {
final String sslConfDir = KeyStoreTestUtil.getClasspathDir(TestKMS.class);
KeyStoreTestUtil.setupSSLConfig(confDir.getAbsolutePath(), sslConfDir,
conf, false);
keystore = confDir.getAbsolutePath() + "/serverKS.jks";
password = "serverP";
} else {
keystore = null;
password = null;
} }
writeConf(confDir, conf); writeConf(confDir, conf);
runServer(null, null, confDir, new KMSCallable<Void>() { runServer(keystore, password, confDir, new KMSCallable<Void>() {
@Override @Override
public Void call() throws Exception { public Void call() throws Exception {
final Configuration clientConf = new Configuration(); final Configuration clientConf = new Configuration();
@ -1830,7 +1866,7 @@ public Void run() throws Exception {
} }
final UserGroupInformation otherUgi; final UserGroupInformation otherUgi;
if (useKrb) { if (kerb) {
UserGroupInformation UserGroupInformation
.loginUserFromKeytab("client1", keytab.getAbsolutePath()); .loginUserFromKeytab("client1", keytab.getAbsolutePath());
otherUgi = UserGroupInformation.getLoginUser(); otherUgi = UserGroupInformation.getLoginUser();
@ -1885,6 +1921,9 @@ public Void run() throws Exception {
return null; return null;
} }
}); });
// Close the client provider. We will verify all providers'
// Truststore reloader threads are closed later.
kp.close();
return null; return null;
} finally { } finally {
otherUgi.logoutUserFromKeytab(); otherUgi.logoutUserFromKeytab();
@ -1894,6 +1933,22 @@ public Void run() throws Exception {
return null; return null;
} }
}); });
// verify that providers created by KMSTokenRenewer are closed.
if (ssl) {
GenericTestUtils.waitFor(new Supplier<Boolean>() {
@Override
public Boolean get() {
final Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for (Thread t : threadSet) {
if (t.getName().contains(SSL_RELOADER_THREAD_NAME)) {
return false;
}
}
return true;
}
}, 1000, 10000);
}
} }
@Test @Test

View File

@ -4569,6 +4569,13 @@ void shutdown() {
if (blockManager != null) { if (blockManager != null) {
blockManager.shutdown(); blockManager.shutdown();
} }
if (provider != null) {
try {
provider.close();
} catch (IOException e) {
LOG.error("Failed to close provider.", e);
}
}
} }
@Override // FSNamesystemMBean @Override // FSNamesystemMBean