From 24da944241a0ab984c26b4ea3f7e2b4fa88b7077 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Fri, 23 Jan 2015 12:11:15 -0800 Subject: [PATCH] HADOOP-11482. Use correct UGI when KMSClientProvider is called by a proxy user. Contributed by Arun Suresh. (cherry picked from commit 4b00935643f6c3656ccbd7eeb54884738bc12c2e) (cherry picked from commit 7b69719455a1a374c9417417ef0c8d7ba6bf593f) --- .../hadoop-common/CHANGES.txt | 3 ++ .../crypto/key/kms/KMSClientProvider.java | 31 +++++++++++++++---- .../hadoop/crypto/key/kms/server/TestKMS.java | 7 +++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index c50b31a19e8..bafd3bf90e5 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -33,6 +33,9 @@ Release 2.6.1 - UNRELEASED HADOOP-11350. The size of header buffer of HttpServer is too small when HTTPS is enabled. (Benoy Antony via wheat9) + 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 c5f09de67e9..11c0b1f6ebd 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 @@ -773,25 +773,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 fa285ca17be..bb6a9aca609 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 @@ -287,6 +287,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", @@ -340,6 +341,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; } }); @@ -349,6 +355,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());