diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index 6bedd4ddb52..6a34092507f 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -756,6 +756,9 @@ Release 2.7.0 - UNRELEASED HADOOP-11507 Hadoop RPC Authentication problem with different user locale. (Talat UYARER via stevel) + HADOOP-11482. Use correct UGI when KMSClientProvider is called by a proxy + user. Contributed by Arun Suresh. + Release 2.6.0 - 2014-11-18 INCOMPATIBLE CHANGES diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/kms/KMSClientProvider.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/kms/KMSClientProvider.java index 0464f553767..97ab2535d9a 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/kms/KMSClientProvider.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/kms/KMSClientProvider.java @@ -787,25 +787,44 @@ public class KMSClientProvider extends KeyProvider implements CryptoExtension, } @Override - public Token[] addDelegationTokens(String renewer, + public Token[] addDelegationTokens(final String renewer, Credentials credentials) throws IOException { Token[] tokens = null; Text dtService = getDelegationTokenService(); Token token = credentials.getToken(dtService); if (token == null) { - URL url = createURL(null, null, null, null); - DelegationTokenAuthenticatedURL authUrl = + final URL url = createURL(null, null, null, null); + final DelegationTokenAuthenticatedURL authUrl = new DelegationTokenAuthenticatedURL(configurator); try { - token = authUrl.getDelegationToken(url, authToken, renewer); + // 'actualUGI' is the UGI of the user creating the client + // It is possible that the creator of the KMSClientProvier + // calls this method on behalf of a proxyUser (the doAsUser). + // In which case this call has to be made as the proxy user. + UserGroupInformation currentUgi = UserGroupInformation.getCurrentUser(); + final String doAsUser = (currentUgi.getAuthenticationMethod() == + UserGroupInformation.AuthenticationMethod.PROXY) + ? currentUgi.getShortUserName() : null; + + token = actualUgi.doAs(new PrivilegedExceptionAction>() { + @Override + public Token run() throws Exception { + // Not using the cached token here.. Creating a new token here + // everytime. + return authUrl.getDelegationToken(url, + new DelegationTokenAuthenticatedURL.Token(), renewer, doAsUser); + } + }); if (token != null) { credentials.addToken(token.getService(), token); tokens = new Token[] { token }; } else { throw new IOException("Got NULL as delegation token"); } - } catch (AuthenticationException ex) { - throw new IOException(ex); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (Exception e) { + throw new IOException(e); } } return tokens; diff --git a/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java b/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java index f487e986658..70ba95f28d7 100644 --- a/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java +++ b/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java @@ -284,6 +284,7 @@ public class TestKMS { password = null; } + conf.set("hadoop.kms.authentication.token.validity", "1"); if (kerberos) { conf.set("hadoop.kms.authentication.type", "kerberos"); conf.set("hadoop.kms.authentication.kerberos.keytab", @@ -337,6 +338,11 @@ public class TestKMS { final KeyProvider kp = new KMSClientProvider(uri, conf); // getKeys() empty Assert.assertTrue(kp.getKeys().isEmpty()); + + Thread.sleep(4000); + Token[] tokens = ((KMSClientProvider)kp).addDelegationTokens("myuser", new Credentials()); + Assert.assertEquals(1, tokens.length); + Assert.assertEquals("kms-dt", tokens[0].getKind().toString()); return null; } }); @@ -346,6 +352,7 @@ public class TestKMS { // getKeys() empty Assert.assertTrue(kp.getKeys().isEmpty()); + Thread.sleep(4000); Token[] tokens = ((KMSClientProvider)kp).addDelegationTokens("myuser", new Credentials()); Assert.assertEquals(1, tokens.length); Assert.assertEquals("kms-dt", tokens[0].getKind().toString());