HADOOP-13255. KMSClientProvider should check and renew tgt when doing delegation token operations. Contributed by Xiao Chen.
This commit is contained in:
parent
127d2c7281
commit
b1674caa40
@ -536,8 +536,6 @@ private HttpURLConnection createConnection(final URL url, String method)
|
|||||||
UserGroupInformation.AuthenticationMethod.PROXY)
|
UserGroupInformation.AuthenticationMethod.PROXY)
|
||||||
? currentUgi.getShortUserName() : null;
|
? currentUgi.getShortUserName() : null;
|
||||||
|
|
||||||
// check and renew TGT to handle potential expiration
|
|
||||||
actualUgi.checkTGTAndReloginFromKeytab();
|
|
||||||
// creating the HTTP connection using the current UGI at constructor time
|
// creating the HTTP connection using the current UGI at constructor time
|
||||||
conn = actualUgi.doAs(new PrivilegedExceptionAction<HttpURLConnection>() {
|
conn = actualUgi.doAs(new PrivilegedExceptionAction<HttpURLConnection>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -103,7 +103,7 @@ public class UserGroupInformation {
|
|||||||
* @param immediate true if we should login without waiting for ticket window
|
* @param immediate true if we should login without waiting for ticket window
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static void setShouldRenewImmediatelyForTests(boolean immediate) {
|
public static void setShouldRenewImmediatelyForTests(boolean immediate) {
|
||||||
shouldRenewImmediatelyForTests = immediate;
|
shouldRenewImmediatelyForTests = immediate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.classification.InterfaceStability;
|
import org.apache.hadoop.classification.InterfaceStability;
|
||||||
import org.apache.hadoop.security.SecurityUtil;
|
import org.apache.hadoop.security.SecurityUtil;
|
||||||
|
import org.apache.hadoop.security.UserGroupInformation;
|
||||||
import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
|
import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
|
||||||
import org.apache.hadoop.security.authentication.client.AuthenticationException;
|
import org.apache.hadoop.security.authentication.client.AuthenticationException;
|
||||||
import org.apache.hadoop.security.authentication.client.Authenticator;
|
import org.apache.hadoop.security.authentication.client.Authenticator;
|
||||||
@ -143,6 +144,8 @@ private void appendDelegationToken(final AuthenticatedURL.Token token,
|
|||||||
public void authenticate(URL url, AuthenticatedURL.Token token)
|
public void authenticate(URL url, AuthenticatedURL.Token token)
|
||||||
throws IOException, AuthenticationException {
|
throws IOException, AuthenticationException {
|
||||||
if (!hasDelegationToken(url, token)) {
|
if (!hasDelegationToken(url, token)) {
|
||||||
|
// check and renew TGT to handle potential expiration
|
||||||
|
UserGroupInformation.getCurrentUser().checkTGTAndReloginFromKeytab();
|
||||||
authenticator.authenticate(url, token);
|
authenticator.authenticate(url, token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,12 +42,9 @@
|
|||||||
import org.apache.hadoop.security.authorize.AuthorizationException;
|
import org.apache.hadoop.security.authorize.AuthorizationException;
|
||||||
import org.apache.hadoop.security.ssl.KeyStoreTestUtil;
|
import org.apache.hadoop.security.ssl.KeyStoreTestUtil;
|
||||||
import org.apache.hadoop.security.token.Token;
|
import org.apache.hadoop.security.token.Token;
|
||||||
import org.apache.hadoop.test.GenericTestUtils;
|
import org.junit.After;
|
||||||
import org.apache.log4j.Level;
|
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.Timeout;
|
import org.junit.rules.Timeout;
|
||||||
@ -88,11 +85,11 @@ public class TestKMS {
|
|||||||
public final Timeout testTimeout = new Timeout(180000);
|
public final Timeout testTimeout = new Timeout(180000);
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void cleanUp() {
|
public void setUp() throws Exception {
|
||||||
|
setUpMiniKdc();
|
||||||
// resetting kerberos security
|
// resetting kerberos security
|
||||||
Configuration conf = new Configuration();
|
Configuration conf = new Configuration();
|
||||||
UserGroupInformation.setConfiguration(conf);
|
UserGroupInformation.setConfiguration(conf);
|
||||||
GenericTestUtils.setLogLevel(LOG, Level.INFO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getTestDir() throws Exception {
|
public static File getTestDir() throws Exception {
|
||||||
@ -232,10 +229,8 @@ public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
|
|||||||
private static MiniKdc kdc;
|
private static MiniKdc kdc;
|
||||||
private static File keytab;
|
private static File keytab;
|
||||||
|
|
||||||
@BeforeClass
|
private static void setUpMiniKdc(Properties kdcConf) throws Exception {
|
||||||
public static void setUpMiniKdc() throws Exception {
|
|
||||||
File kdcDir = getTestDir();
|
File kdcDir = getTestDir();
|
||||||
Properties kdcConf = MiniKdc.createConf();
|
|
||||||
kdc = new MiniKdc(kdcConf, kdcDir);
|
kdc = new MiniKdc(kdcConf, kdcDir);
|
||||||
kdc.start();
|
kdc.start();
|
||||||
keytab = new File(kdcDir, "keytab");
|
keytab = new File(kdcDir, "keytab");
|
||||||
@ -255,11 +250,18 @@ public static void setUpMiniKdc() throws Exception {
|
|||||||
principals.toArray(new String[principals.size()]));
|
principals.toArray(new String[principals.size()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
private void setUpMiniKdc() throws Exception {
|
||||||
public static void tearDownMiniKdc() throws Exception {
|
Properties kdcConf = MiniKdc.createConf();
|
||||||
|
setUpMiniKdc(kdcConf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDownMiniKdc() throws Exception {
|
||||||
if (kdc != null) {
|
if (kdc != null) {
|
||||||
kdc.stop();
|
kdc.stop();
|
||||||
|
kdc = null;
|
||||||
}
|
}
|
||||||
|
UserGroupInformation.setShouldRenewImmediatelyForTests(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T doAs(String user, final PrivilegedExceptionAction<T> action)
|
private <T> T doAs(String user, final PrivilegedExceptionAction<T> action)
|
||||||
@ -2053,6 +2055,73 @@ public void testWebHDFSProxyUserSimple() throws Exception {
|
|||||||
doWebHDFSProxyUserTest(false);
|
doWebHDFSProxyUserTest(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTGTRenewal() throws Exception {
|
||||||
|
tearDownMiniKdc();
|
||||||
|
Properties kdcConf = MiniKdc.createConf();
|
||||||
|
kdcConf.setProperty(MiniKdc.MAX_TICKET_LIFETIME, "3");
|
||||||
|
kdcConf.setProperty(MiniKdc.MIN_TICKET_LIFETIME, "3");
|
||||||
|
setUpMiniKdc(kdcConf);
|
||||||
|
|
||||||
|
Configuration conf = new Configuration();
|
||||||
|
conf.set("hadoop.security.authentication", "kerberos");
|
||||||
|
UserGroupInformation.setConfiguration(conf);
|
||||||
|
final File testDir = getTestDir();
|
||||||
|
conf = createBaseKMSConf(testDir);
|
||||||
|
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");
|
||||||
|
conf.set("hadoop.kms.proxyuser.client.users", "*");
|
||||||
|
conf.set("hadoop.kms.proxyuser.client.hosts", "*");
|
||||||
|
writeConf(testDir, conf);
|
||||||
|
|
||||||
|
runServer(null, null, testDir, new KMSCallable<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
final Configuration conf = new Configuration();
|
||||||
|
final URI uri = createKMSUri(getKMSUrl());
|
||||||
|
UserGroupInformation.setShouldRenewImmediatelyForTests(true);
|
||||||
|
UserGroupInformation
|
||||||
|
.loginUserFromKeytab("client", keytab.getAbsolutePath());
|
||||||
|
final UserGroupInformation clientUgi =
|
||||||
|
UserGroupInformation.getCurrentUser();
|
||||||
|
clientUgi.doAs(new PrivilegedExceptionAction<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void run() throws Exception {
|
||||||
|
// Verify getKeys can relogin
|
||||||
|
Thread.sleep(3100);
|
||||||
|
KeyProvider kp = createProvider(uri, conf);
|
||||||
|
kp.getKeys();
|
||||||
|
|
||||||
|
// Verify addDelegationTokens can relogin
|
||||||
|
// (different code path inside KMSClientProvider than getKeys)
|
||||||
|
Thread.sleep(3100);
|
||||||
|
kp = createProvider(uri, conf);
|
||||||
|
((KeyProviderDelegationTokenExtension.DelegationTokenExtension) kp)
|
||||||
|
.addDelegationTokens("myuser", new Credentials());
|
||||||
|
|
||||||
|
// Verify getKeys can relogin with proxy user
|
||||||
|
UserGroupInformation anotherUgi =
|
||||||
|
UserGroupInformation.createProxyUser("client1", clientUgi);
|
||||||
|
anotherUgi.doAs(new PrivilegedExceptionAction<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void run() throws Exception {
|
||||||
|
Thread.sleep(3100);
|
||||||
|
KeyProvider kp = createProvider(uri, conf);
|
||||||
|
kp.getKeys();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void doWebHDFSProxyUserTest(final boolean kerberos) throws Exception {
|
public void doWebHDFSProxyUserTest(final boolean kerberos) throws Exception {
|
||||||
Configuration conf = new Configuration();
|
Configuration conf = new Configuration();
|
||||||
conf.set("hadoop.security.authentication", "kerberos");
|
conf.set("hadoop.security.authentication", "kerberos");
|
||||||
|
@ -22,7 +22,7 @@ log4j.appender.stdout.Target=System.out
|
|||||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||||
log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p %c{1} - %m%n
|
log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p %c{1} - %m%n
|
||||||
|
|
||||||
log4j.rootLogger=WARN, stdout
|
log4j.rootLogger=INFO, stdout
|
||||||
log4j.logger.org.apache.hadoop.conf=ERROR
|
log4j.logger.org.apache.hadoop.conf=ERROR
|
||||||
log4j.logger.org.apache.hadoop.crytpo.key.kms.server=ALL
|
log4j.logger.org.apache.hadoop.crytpo.key.kms.server=ALL
|
||||||
log4j.logger.com.sun.jersey.server.wadl.generators.WadlGeneratorJAXBGrammarGenerator=OFF
|
log4j.logger.com.sun.jersey.server.wadl.generators.WadlGeneratorJAXBGrammarGenerator=OFF
|
||||||
|
@ -147,6 +147,7 @@ public void run() {
|
|||||||
public static final String KDC_PORT = "kdc.port";
|
public static final String KDC_PORT = "kdc.port";
|
||||||
public static final String INSTANCE = "instance";
|
public static final String INSTANCE = "instance";
|
||||||
public static final String MAX_TICKET_LIFETIME = "max.ticket.lifetime";
|
public static final String MAX_TICKET_LIFETIME = "max.ticket.lifetime";
|
||||||
|
public static final String MIN_TICKET_LIFETIME = "min.ticket.lifetime";
|
||||||
public static final String MAX_RENEWABLE_LIFETIME = "max.renewable.lifetime";
|
public static final String MAX_RENEWABLE_LIFETIME = "max.renewable.lifetime";
|
||||||
public static final String TRANSPORT = "transport";
|
public static final String TRANSPORT = "transport";
|
||||||
public static final String DEBUG = "debug";
|
public static final String DEBUG = "debug";
|
||||||
@ -280,7 +281,7 @@ public synchronized void start() throws Exception {
|
|||||||
simpleKdc.init();
|
simpleKdc.init();
|
||||||
resetDefaultRealm();
|
resetDefaultRealm();
|
||||||
simpleKdc.start();
|
simpleKdc.start();
|
||||||
LOG.info("MiniKdc stated.");
|
LOG.info("MiniKdc started.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetDefaultRealm() throws IOException {
|
private void resetDefaultRealm() throws IOException {
|
||||||
@ -321,6 +322,14 @@ private void prepareKdcServer() throws Exception {
|
|||||||
if (conf.getProperty(DEBUG) != null) {
|
if (conf.getProperty(DEBUG) != null) {
|
||||||
krb5Debug = getAndSet(SUN_SECURITY_KRB5_DEBUG, conf.getProperty(DEBUG));
|
krb5Debug = getAndSet(SUN_SECURITY_KRB5_DEBUG, conf.getProperty(DEBUG));
|
||||||
}
|
}
|
||||||
|
if (conf.getProperty(MIN_TICKET_LIFETIME) != null) {
|
||||||
|
simpleKdc.getKdcConfig().setLong(KdcConfigKey.MINIMUM_TICKET_LIFETIME,
|
||||||
|
Long.parseLong(conf.getProperty(MIN_TICKET_LIFETIME)));
|
||||||
|
}
|
||||||
|
if (conf.getProperty(MAX_TICKET_LIFETIME) != null) {
|
||||||
|
simpleKdc.getKdcConfig().setLong(KdcConfigKey.MAXIMUM_TICKET_LIFETIME,
|
||||||
|
Long.parseLong(conf.getProperty(MiniKdc.MAX_TICKET_LIFETIME)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user