commit 7257937277156047df67473a521439568181a621 Author: Mithun RK Date: Fri Sep 8 15:45:34 2017 -0700 HIVE-17489: Separate client-facing and server-side Kerberos principals, to support HA diff --git a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java index b8052c6f07..717773b64e 100644 --- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java +++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java @@ -705,6 +705,9 @@ private static void populateLlapDaemonVarsSet(Set llapDaemonVarsSetLocal "hive-metastore/_HOST@EXAMPLE.COM", "The service principal for the metastore Thrift server. \n" + "The special string _HOST will be replaced automatically with the correct host name."), + METASTORE_CLIENT_KERBEROS_PRINCIPAL("hive.metastore.client.kerberos.principal", + "hive-metastore/_HOST@EXAMPLE.COM", + "The Kerberos principal associated with the HA cluster of hcat_servers."), METASTORE_USE_THRIFT_SASL("hive.metastore.sasl.enabled", false, "If true, the metastore Thrift interface will be secured with SASL. Clients must authenticate with Kerberos."), METASTORE_USE_THRIFT_FRAMED_TRANSPORT("hive.metastore.thrift.framed.transport.enabled", false, @@ -2489,6 +2492,8 @@ private static void populateLlapDaemonVarsSet(Set llapDaemonVarsSetLocal "Kerberos keytab file for server principal"), HIVE_SERVER2_KERBEROS_PRINCIPAL("hive.server2.authentication.kerberos.principal", "", "Kerberos server principal"), + HIVE_SERVER2_CLIENT_KERBEROS_PRINCIPAL("hive.server2.authentication.client.kerberos.principal", "", + "Kerberos principal used by the HA hive_server2s."), HIVE_SERVER2_SPNEGO_KEYTAB("hive.server2.authentication.spnego.keytab", "", "keytab file for SPNego principal, optional,\n" + "typical value would look like /etc/security/keytabs/spnego.service.keytab,\n" + diff --git a/itests/hive-unit-hadoop2/src/test/java/org/apache/hadoop/hive/thrift/TestHadoopAuthBridge23.java b/itests/hive-unit-hadoop2/src/test/java/org/apache/hadoop/hive/thrift/TestHadoopAuthBridge23.java index 7e5005cdcf..f5ec3d1a8a 100644 --- a/itests/hive-unit-hadoop2/src/test/java/org/apache/hadoop/hive/thrift/TestHadoopAuthBridge23.java +++ b/itests/hive-unit-hadoop2/src/test/java/org/apache/hadoop/hive/thrift/TestHadoopAuthBridge23.java @@ -85,7 +85,7 @@ public void init(Object hmsHandler, ServerMode smode) throws TokenStoreException private static class MyHadoopThriftAuthBridge23 extends HadoopThriftAuthBridge23 { @Override - public Server createServer(String keytabFile, String principalConf) + public Server createServer(String keytabFile, String principalConf, String clientConf) throws TTransportException { //Create a Server that doesn't interpret any Kerberos stuff return new Server(); diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java b/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java index 4ac9269f6a..703419d0c5 100644 --- a/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java +++ b/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java @@ -7168,7 +7168,8 @@ public static void startMetaStore(int port, HadoopThriftAuthBridge bridge, } saslServer = bridge.createServer( conf.getVar(HiveConf.ConfVars.METASTORE_KERBEROS_KEYTAB_FILE), - conf.getVar(HiveConf.ConfVars.METASTORE_KERBEROS_PRINCIPAL)); + conf.getVar(HiveConf.ConfVars.METASTORE_KERBEROS_PRINCIPAL), + conf.getVar(HiveConf.ConfVars.METASTORE_CLIENT_KERBEROS_PRINCIPAL)); // Start delegation token manager delegationTokenManager = new HiveDelegationTokenManager(); delegationTokenManager.startDelegationTokenSecretManager(conf, baseHandler, diff --git a/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java b/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java index dcb6338d39..d43c486da4 100644 --- a/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java +++ b/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java @@ -108,7 +108,8 @@ public HiveAuthFactory(HiveConf conf) throws TTransportException { saslServer = ShimLoader.getHadoopThriftAuthBridge().createServer( conf.getVar(ConfVars.HIVE_SERVER2_KERBEROS_KEYTAB), - conf.getVar(ConfVars.HIVE_SERVER2_KERBEROS_PRINCIPAL)); + conf.getVar(ConfVars.HIVE_SERVER2_KERBEROS_PRINCIPAL), + conf.getVar(ConfVars.HIVE_SERVER2_CLIENT_KERBEROS_PRINCIPAL)); // Start delegation token manager delegationTokenManager = new HiveDelegationTokenManager(); diff --git a/shims/common/src/main/java/org/apache/hadoop/hive/thrift/HadoopThriftAuthBridge.java b/shims/common/src/main/java/org/apache/hadoop/hive/thrift/HadoopThriftAuthBridge.java index c59ac5b66b..668bbc7646 100644 --- a/shims/common/src/main/java/org/apache/hadoop/hive/thrift/HadoopThriftAuthBridge.java +++ b/shims/common/src/main/java/org/apache/hadoop/hive/thrift/HadoopThriftAuthBridge.java @@ -98,8 +98,8 @@ public Client createClientWithConf(String authMethod) { } } - public Server createServer(String keytabFile, String principalConf) throws TTransportException { - return new Server(keytabFile, principalConf); + public Server createServer(String keytabFile, String principalConf, String clientConf) throws TTransportException { + return new Server(keytabFile, principalConf, clientConf); } @@ -309,11 +309,13 @@ static String encodeIdentifier(byte[] identifier) { }; protected final UserGroupInformation realUgi; + protected final UserGroupInformation clientValidationUGI; protected DelegationTokenSecretManager secretManager; public Server() throws TTransportException { try { realUgi = UserGroupInformation.getCurrentUser(); + clientValidationUGI = UserGroupInformation.getCurrentUser(); } catch (IOException ioe) { throw new TTransportException(ioe); } @@ -321,7 +323,7 @@ public Server() throws TTransportException { /** * Create a server with a kerberos keytab/principal. */ - protected Server(String keytabFile, String principalConf) + protected Server(String keytabFile, String principalConf, String clientConf) throws TTransportException { if (keytabFile == null || keytabFile.isEmpty()) { throw new TTransportException("No keytab specified"); @@ -329,10 +331,24 @@ protected Server(String keytabFile, String principalConf) if (principalConf == null || principalConf.isEmpty()) { throw new TTransportException("No principal specified"); } + if (clientConf == null || clientConf.isEmpty()) { + // Don't bust existing setups. + LOG.warn("Client-facing principal not set. Using server-side setting: " + principalConf); + clientConf = principalConf; + } // Login from the keytab String kerberosName; try { + LOG.info("Logging in via CLIENT based principal "); + kerberosName = + SecurityUtil.getServerPrincipal(clientConf, "0.0.0.0"); + UserGroupInformation.loginUserFromKeytab( + kerberosName, keytabFile); + clientValidationUGI = UserGroupInformation.getLoginUser(); + assert clientValidationUGI.isFromKeytab(); + + LOG.info("Logging in via SERVER based principal "); kerberosName = SecurityUtil.getServerPrincipal(principalConf, "0.0.0.0"); UserGroupInformation.loginUserFromKeytab( @@ -362,7 +378,7 @@ public TTransportFactory createTransportFactory(Map saslProps) TSaslServerTransport.Factory transFactory = createSaslServerTransportFactory(saslProps); - return new TUGIAssumingTransportFactory(transFactory, realUgi); + return new TUGIAssumingTransportFactory(transFactory, clientValidationUGI); } /** @@ -374,7 +390,7 @@ public TTransportFactory createTransportFactory(Map saslProps) public TSaslServerTransport.Factory createSaslServerTransportFactory( Map saslProps) throws TTransportException { // Parse out the kerberos principal, host, realm. - String kerberosName = realUgi.getUserName(); + String kerberosName = clientValidationUGI.getUserName(); final String names[] = SaslRpcServer.splitKerberosName(kerberosName); if (names.length != 3) { throw new TTransportException("Kerberos principal should have 3 parts: " + kerberosName);