diff --git a/llap-client/pom.xml b/llap-client/pom.xml index 6923c3505b2635b4ee95697b47487d97f3f1484d..84e87ec36d368d80305e0ac1a97d25d2fb9e0322 100644 --- a/llap-client/pom.xml +++ b/llap-client/pom.xml @@ -156,6 +156,18 @@ + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + + + org.powermock + powermock-api-mockito + ${powermock.version} + test + ${basedir}/src/java diff --git a/llap-client/src/java/org/apache/hadoop/hive/registry/impl/ZookeeperUtils.java b/llap-client/src/java/org/apache/hadoop/hive/registry/impl/ZookeeperUtils.java index be7657a5080b78df806994af8c492140384c3926..c3d34c486dc072689510873a413ea19195dc3de8 100644 --- a/llap-client/src/java/org/apache/hadoop/hive/registry/impl/ZookeeperUtils.java +++ b/llap-client/src/java/org/apache/hadoop/hive/registry/impl/ZookeeperUtils.java @@ -55,14 +55,19 @@ public static String setupZookeeperAuth(Configuration conf, String saslLoginCont /** * Check if Kerberos authentication is enabled. + * This is used by: + * - LLAP daemons + * - Tez AM + * - HS2 + * - LLAP status service + * Among the these Tez AM process has the lowest security setting wrt Kerberos in UGI. + * Even in secure scenarios Tez AM will return false for + * UGI.getLoginUser().hasKerberosCredentials() as it does not log in using Kerberos. + * Hence UGI.isSecurityEnabled() is the tightest setting we can check against. */ public static boolean isKerberosEnabled(Configuration conf) { - try { - return UserGroupInformation.getLoginUser().hasKerberosCredentials() && + return UserGroupInformation.isSecurityEnabled() && HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_ZOOKEEPER_USE_KERBEROS); - } catch (IOException e) { - return false; - } } /** diff --git a/llap-client/src/test/org/apache/hadoop/hive/registry/impl/TestZookeeperUtils.java b/llap-client/src/test/org/apache/hadoop/hive/registry/impl/TestZookeeperUtils.java index 46e74380c2409783ece8cbbcc010f0112c98d3b9..0f2cae6d76ceb6e71fa9e3ebd8f86efc85fa668a 100644 --- a/llap-client/src/test/org/apache/hadoop/hive/registry/impl/TestZookeeperUtils.java +++ b/llap-client/src/test/org/apache/hadoop/hive/registry/impl/TestZookeeperUtils.java @@ -24,11 +24,18 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.BDDMockito; import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; /** * ZookeeperUtils test suite. */ +@RunWith(PowerMockRunner.class) +@PrepareForTest(UserGroupInformation.class) public class TestZookeeperUtils { private Configuration conf; @@ -37,18 +44,26 @@ @Before public void setup() { conf = new Configuration(); + PowerMockito.mockStatic(UserGroupInformation.class); + BDDMockito.given(UserGroupInformation.isSecurityEnabled()).willReturn(true); ugi = Mockito.mock(UserGroupInformation.class); UserGroupInformation.setLoginUser(ugi); } + /** + * Secure scenario, invoked e.g. from within HS2 or LLAP daemon process, kinit'ed inside proc. + */ @Test - public void testHadoopAuthKerberosAndZookeeperUseKerberos() { + public void testHadoopAuthKerberosFromKeytabAndZookeeperUseKerberos() { Mockito.when(ugi.hasKerberosCredentials()).thenReturn(true); Mockito.when(ugi.isFromKeytab()).thenReturn(true); Assert.assertTrue(HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_ZOOKEEPER_USE_KERBEROS)); Assert.assertTrue(ZookeeperUtils.isKerberosEnabled(conf)); } + /** + * Secure scenario, invoked e.g. from within HS2 or LLAP status process, kinit'ed in parent proc. + */ @Test public void testHadoopAuthKerberosFromTicketAndZookeeperUseKerberos() { Mockito.when(ugi.hasKerberosCredentials()).thenReturn(true); @@ -57,17 +72,36 @@ public void testHadoopAuthKerberosFromTicketAndZookeeperUseKerberos() { Assert.assertTrue(ZookeeperUtils.isKerberosEnabled(conf)); } + /** + * Secure scenario, invoked e.g. from within Tez AM process. + */ @Test - public void testHadoopAuthKerberosAndZookeeperNoKerberos(){ - Mockito.when(ugi.hasKerberosCredentials()).thenReturn(true); - conf.setBoolean(HiveConf.ConfVars.HIVE_ZOOKEEPER_USE_KERBEROS.varname, false); - Assert.assertFalse(ZookeeperUtils.isKerberosEnabled(conf)); + public void testHadoopAuthKerberosNoLoginAndZookeeperUseKerberos() { + Mockito.when(ugi.hasKerberosCredentials()).thenReturn(false); + Mockito.when(ugi.isFromKeytab()).thenReturn(false); + Assert.assertTrue(HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_ZOOKEEPER_USE_KERBEROS)); + Assert.assertTrue(ZookeeperUtils.isKerberosEnabled(conf)); } + /** + * Unsecure scenario. + */ @Test - public void testHadoopAuthSimpleAndZookeeperKerberos(){ + public void testHadoopAuthSimpleAndZookeeperUseKerberos() { + BDDMockito.given(UserGroupInformation.isSecurityEnabled()).willReturn(false); Mockito.when(ugi.hasKerberosCredentials()).thenReturn(false); + Mockito.when(ugi.isFromKeytab()).thenReturn(false); + Assert.assertTrue(HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_ZOOKEEPER_USE_KERBEROS)); + Assert.assertFalse(ZookeeperUtils.isKerberosEnabled(conf)); + } + + /** + * Secure scenario with hive.zookeeper.kerberos.enabled=false. + */ + @Test + public void testHadoopAuthKerberosAndZookeeperNoKerberos(){ conf.setBoolean(HiveConf.ConfVars.HIVE_ZOOKEEPER_USE_KERBEROS.varname, false); Assert.assertFalse(ZookeeperUtils.isKerberosEnabled(conf)); } + } diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/tez/TezSessionState.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/tez/TezSessionState.java index b4cdcb538deef9f2ff58c889b2a7b3d952e52344..8becef1cd3a7534813e5479d7a59b5f8b49bf465 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/exec/tez/TezSessionState.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/tez/TezSessionState.java @@ -392,6 +392,14 @@ public TezClient call() throws Exception { } } + /** + * Check if Kerberos authentication is enabled. + * This is used by: + * - HS2 (upon Tez session creation) + * In secure scenarios HS2 might either be logged on (by Kerberos) by itself or by a launcher + * script it was forked from. In the latter case UGI.getLoginUser().isFromKeytab() returns false, + * hence UGI.getLoginUser().hasKerberosCredentials() is a tightest setting we can check against. + */ private boolean isKerberosEnabled(Configuration conf) { try { return UserGroupInformation.getLoginUser().hasKerberosCredentials() && diff --git a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/security/ZooKeeperTokenStore.java b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/security/ZooKeeperTokenStore.java index 785fa02854099f959171dc6438775787ca36132b..da28fed825d7bbb131bf9cf86afdec3b4a3977f3 100644 --- a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/security/ZooKeeperTokenStore.java +++ b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/security/ZooKeeperTokenStore.java @@ -93,9 +93,17 @@ return nodeAcls; } + /** + * Check if Kerberos authentication is enabled. + * This is used by: + * - HMS + * In secure scenarios the HMS is logged in (by itself) using Kerberos keytab, hence + * UGI.getLoginUser().isFromKeytab() returns true. + * This makes checking against this method the tightest setting we can check against. + */ private boolean isKerberosEnabled(Configuration conf) { try { - return UserGroupInformation.getLoginUser().hasKerberosCredentials() && + return UserGroupInformation.getLoginUser().isFromKeytab() && MetastoreConf.getBoolVar(conf, MetastoreConf.ConfVars.THRIFT_ZOOKEEPER_USE_KERBEROS); } catch (IOException e) { return false;