Skip to content

Commit f3132ee

Browse files
committed
HADOOP-11176. KMSClientProvider authentication fails when both currentUgi and loginUgi are a proxied user. Contributed by Arun Suresh.
(cherry picked from commit 0e57aa3)
1 parent 8845517 commit f3132ee

File tree

3 files changed

+155
-17
lines changed

3 files changed

+155
-17
lines changed

hadoop-common-project/hadoop-common/CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,9 @@ Release 2.6.0 - UNRELEASED
486486
HADOOP-11193. Fix uninitialized variables in NativeIO.c
487487
(Xiaoyu Yao via wheat9)
488488

489+
HADOOP-11176. KMSClientProvider authentication fails when both currentUgi
490+
and loginUgi are a proxied user. (Arun Suresh via atm)
491+
489492
BREAKDOWN OF HDFS-6134 AND HADOOP-10150 SUBTASKS AND RELATED JIRAS
490493

491494
HADOOP-10734. Implement high-performance secure random number sources.

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/kms/KMSClientProvider.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,8 @@ public static String checkNotEmpty(String s, String name)
251251
private SSLFactory sslFactory;
252252
private ConnectionConfigurator configurator;
253253
private DelegationTokenAuthenticatedURL.Token authToken;
254-
private UserGroupInformation loginUgi;
255254
private final int authRetry;
255+
private final UserGroupInformation actualUgi;
256256

257257
@Override
258258
public String toString() {
@@ -336,7 +336,11 @@ public KMSClientProvider(URI uri, Configuration conf) throws IOException {
336336
KMS_CLIENT_ENC_KEY_CACHE_NUM_REFILL_THREADS_DEFAULT),
337337
new EncryptedQueueRefiller());
338338
authToken = new DelegationTokenAuthenticatedURL.Token();
339-
loginUgi = UserGroupInformation.getCurrentUser();
339+
actualUgi =
340+
(UserGroupInformation.getCurrentUser().getAuthenticationMethod() ==
341+
UserGroupInformation.AuthenticationMethod.PROXY) ? UserGroupInformation
342+
.getCurrentUser().getRealUser() : UserGroupInformation
343+
.getCurrentUser();
340344
}
341345

342346
private String createServiceURL(URL url) throws IOException {
@@ -407,7 +411,7 @@ private HttpURLConnection createConnection(final URL url, String method)
407411
? currentUgi.getShortUserName() : null;
408412

409413
// creating the HTTP connection using the current UGI at constructor time
410-
conn = loginUgi.doAs(new PrivilegedExceptionAction<HttpURLConnection>() {
414+
conn = actualUgi.doAs(new PrivilegedExceptionAction<HttpURLConnection>() {
411415
@Override
412416
public HttpURLConnection run() throws Exception {
413417
DelegationTokenAuthenticatedURL authUrl =
@@ -457,8 +461,6 @@ private <T> T call(HttpURLConnection conn, Map jsonOutput,
457461
// WWW-Authenticate header as well)..
458462
KMSClientProvider.this.authToken =
459463
new DelegationTokenAuthenticatedURL.Token();
460-
KMSClientProvider.this.loginUgi =
461-
UserGroupInformation.getCurrentUser();
462464
if (authRetryCount > 0) {
463465
String contentType = conn.getRequestProperty(CONTENT_TYPE);
464466
String requestMethod = conn.getRequestMethod();
@@ -475,9 +477,6 @@ private <T> T call(HttpURLConnection conn, Map jsonOutput,
475477
// Ignore the AuthExceptions.. since we are just using the method to
476478
// extract and set the authToken.. (Workaround till we actually fix
477479
// AuthenticatedURL properly to set authToken post initialization)
478-
} finally {
479-
KMSClientProvider.this.loginUgi =
480-
UserGroupInformation.getCurrentUser();
481480
}
482481
HttpExceptionUtils.validateResponse(conn, expectedResponse);
483482
if (APPLICATION_JSON_MIME.equalsIgnoreCase(conn.getContentType())

hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java

Lines changed: 145 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,22 +1585,34 @@ public Void run() throws Exception {
15851585
}
15861586

15871587
@Test
1588-
public void testProxyUser() throws Exception {
1588+
public void testProxyUserKerb() throws Exception {
1589+
doProxyUserTest(true);
1590+
}
1591+
1592+
@Test
1593+
public void testProxyUserSimple() throws Exception {
1594+
doProxyUserTest(false);
1595+
}
1596+
1597+
public void doProxyUserTest(final boolean kerberos) throws Exception {
15891598
Configuration conf = new Configuration();
15901599
conf.set("hadoop.security.authentication", "kerberos");
15911600
UserGroupInformation.setConfiguration(conf);
15921601
final File testDir = getTestDir();
15931602
conf = createBaseKMSConf(testDir);
1594-
conf.set("hadoop.kms.authentication.type", "kerberos");
1603+
if (kerberos) {
1604+
conf.set("hadoop.kms.authentication.type", "kerberos");
1605+
}
15951606
conf.set("hadoop.kms.authentication.kerberos.keytab",
15961607
keytab.getAbsolutePath());
15971608
conf.set("hadoop.kms.authentication.kerberos.principal", "HTTP/localhost");
15981609
conf.set("hadoop.kms.authentication.kerberos.name.rules", "DEFAULT");
1599-
conf.set("hadoop.kms.proxyuser.client.users", "foo");
1610+
conf.set("hadoop.kms.proxyuser.client.users", "foo,bar");
16001611
conf.set("hadoop.kms.proxyuser.client.hosts", "*");
1601-
conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "kAA.ALL", "*");
1602-
conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "kBB.ALL", "*");
1603-
conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "kCC.ALL", "*");
1612+
conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "kAA.ALL", "client");
1613+
conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "kBB.ALL", "foo");
1614+
conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "kCC.ALL", "foo1");
1615+
conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "kDD.ALL", "bar");
16041616

16051617
writeConf(testDir, conf);
16061618

@@ -1611,9 +1623,16 @@ public Void call() throws Exception {
16111623
conf.setInt(KeyProvider.DEFAULT_BITLENGTH_NAME, 64);
16121624
final URI uri = createKMSUri(getKMSUrl());
16131625

1614-
// proxyuser client using kerberos credentials
1615-
final UserGroupInformation clientUgi = UserGroupInformation.
1616-
loginUserFromKeytabAndReturnUGI("client", keytab.getAbsolutePath());
1626+
UserGroupInformation proxyUgi = null;
1627+
if (kerberos) {
1628+
// proxyuser client using kerberos credentials
1629+
proxyUgi = UserGroupInformation.
1630+
loginUserFromKeytabAndReturnUGI("client", keytab.getAbsolutePath());
1631+
} else {
1632+
proxyUgi = UserGroupInformation.createRemoteUser("client");
1633+
}
1634+
1635+
final UserGroupInformation clientUgi = proxyUgi;
16171636
clientUgi.doAs(new PrivilegedExceptionAction<Void>() {
16181637
@Override
16191638
public Void run() throws Exception {
@@ -1649,6 +1668,123 @@ public Void run() throws Exception {
16491668
return null;
16501669
}
16511670
});
1671+
1672+
// authorized proxyuser
1673+
UserGroupInformation barUgi =
1674+
UserGroupInformation.createProxyUser("bar", clientUgi);
1675+
barUgi.doAs(new PrivilegedExceptionAction<Void>() {
1676+
@Override
1677+
public Void run() throws Exception {
1678+
Assert.assertNotNull(kp.createKey("kDD",
1679+
new KeyProvider.Options(conf)));
1680+
return null;
1681+
}
1682+
});
1683+
return null;
1684+
}
1685+
});
1686+
1687+
return null;
1688+
}
1689+
});
1690+
}
1691+
1692+
@Test
1693+
public void testWebHDFSProxyUserKerb() throws Exception {
1694+
doWebHDFSProxyUserTest(true);
1695+
}
1696+
1697+
@Test
1698+
public void testWebHDFSProxyUserSimple() throws Exception {
1699+
doWebHDFSProxyUserTest(false);
1700+
}
1701+
1702+
public void doWebHDFSProxyUserTest(final boolean kerberos) throws Exception {
1703+
Configuration conf = new Configuration();
1704+
conf.set("hadoop.security.authentication", "kerberos");
1705+
UserGroupInformation.setConfiguration(conf);
1706+
final File testDir = getTestDir();
1707+
conf = createBaseKMSConf(testDir);
1708+
if (kerberos) {
1709+
conf.set("hadoop.kms.authentication.type", "kerberos");
1710+
}
1711+
conf.set("hadoop.kms.authentication.kerberos.keytab",
1712+
keytab.getAbsolutePath());
1713+
conf.set("hadoop.kms.authentication.kerberos.principal", "HTTP/localhost");
1714+
conf.set("hadoop.kms.authentication.kerberos.name.rules", "DEFAULT");
1715+
conf.set("hadoop.security.kms.client.timeout", "300");
1716+
conf.set("hadoop.kms.proxyuser.client.users", "foo,bar");
1717+
conf.set("hadoop.kms.proxyuser.client.hosts", "*");
1718+
conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "kAA.ALL", "foo");
1719+
conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "kBB.ALL", "foo1");
1720+
conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "kCC.ALL", "bar");
1721+
1722+
writeConf(testDir, conf);
1723+
1724+
runServer(null, null, testDir, new KMSCallable<Void>() {
1725+
@Override
1726+
public Void call() throws Exception {
1727+
final Configuration conf = new Configuration();
1728+
conf.setInt(KeyProvider.DEFAULT_BITLENGTH_NAME, 64);
1729+
final URI uri = createKMSUri(getKMSUrl());
1730+
1731+
UserGroupInformation proxyUgi = null;
1732+
if (kerberos) {
1733+
// proxyuser client using kerberos credentials
1734+
proxyUgi = UserGroupInformation.
1735+
loginUserFromKeytabAndReturnUGI("client", keytab.getAbsolutePath());
1736+
} else {
1737+
proxyUgi = UserGroupInformation.createRemoteUser("client");
1738+
}
1739+
1740+
final UserGroupInformation clientUgi = proxyUgi;
1741+
clientUgi.doAs(new PrivilegedExceptionAction<Void>() {
1742+
@Override
1743+
public Void run() throws Exception {
1744+
1745+
// authorized proxyuser
1746+
UserGroupInformation fooUgi =
1747+
UserGroupInformation.createProxyUser("foo", clientUgi);
1748+
fooUgi.doAs(new PrivilegedExceptionAction<Void>() {
1749+
@Override
1750+
public Void run() throws Exception {
1751+
KeyProvider kp = new KMSClientProvider(uri, conf);
1752+
Assert.assertNotNull(kp.createKey("kAA",
1753+
new KeyProvider.Options(conf)));
1754+
return null;
1755+
}
1756+
});
1757+
1758+
// unauthorized proxyuser
1759+
UserGroupInformation foo1Ugi =
1760+
UserGroupInformation.createProxyUser("foo1", clientUgi);
1761+
foo1Ugi.doAs(new PrivilegedExceptionAction<Void>() {
1762+
@Override
1763+
public Void run() throws Exception {
1764+
try {
1765+
KeyProvider kp = new KMSClientProvider(uri, conf);
1766+
kp.createKey("kBB", new KeyProvider.Options(conf));
1767+
Assert.fail();
1768+
} catch (Exception ex) {
1769+
Assert.assertTrue(ex.getMessage(), ex.getMessage().contains("Forbidden"));
1770+
}
1771+
return null;
1772+
}
1773+
});
1774+
1775+
// authorized proxyuser
1776+
UserGroupInformation barUgi =
1777+
UserGroupInformation.createProxyUser("bar", clientUgi);
1778+
barUgi.doAs(new PrivilegedExceptionAction<Void>() {
1779+
@Override
1780+
public Void run() throws Exception {
1781+
KeyProvider kp = new KMSClientProvider(uri, conf);
1782+
Assert.assertNotNull(kp.createKey("kCC",
1783+
new KeyProvider.Options(conf)));
1784+
return null;
1785+
}
1786+
});
1787+
16521788
return null;
16531789
}
16541790
});

0 commit comments

Comments
 (0)