Repository: hive Updated Branches: refs/heads/master 7dc701c59 -> c9f56052c
HIVE-17489: Separate client-facing and server-side Kerberos principals, to support HA (Thiruvel Thirumoolan, reviewed by Mithun Radhakrishnan) Project: http://git-wip-us.apache.org/repos/asf/hive/repo Commit: http://git-wip-us.apache.org/repos/asf/hive/commit/c9f56052 Tree: http://git-wip-us.apache.org/repos/asf/hive/tree/c9f56052 Diff: http://git-wip-us.apache.org/repos/asf/hive/diff/c9f56052 Branch: refs/heads/master Commit: c9f56052cf789734cfdca177e3a109fca28a3eef Parents: 7dc701c Author: Mithun RK <mit...@apache.org> Authored: Fri Sep 8 15:31:09 2017 -0700 Committer: Mithun RK <mit...@apache.org> Committed: Fri Sep 29 17:56:54 2017 -0700 ---------------------------------------------------------------------- .../org/apache/hadoop/hive/conf/HiveConf.java | 5 ++++ .../security/TestHadoopAuthBridge23.java | 2 +- .../hadoop/hive/metastore/HiveMetaStore.java | 3 ++- .../hive/service/auth/HiveAuthFactory.java | 3 ++- .../hive/thrift/HadoopThriftAuthBridge.java | 27 +++++++++++++++----- .../security/HadoopThriftAuthBridge.java | 26 +++++++++++++++---- 6 files changed, 52 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hive/blob/c9f56052/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java ---------------------------------------------------------------------- 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 cd6998e..ce391fd 100644 --- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java +++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java @@ -685,6 +685,9 @@ public class HiveConf extends Configuration { "hive-metastore/_h...@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", + "", // E.g. "hive-metastore/_h...@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, @@ -2564,6 +2567,8 @@ public class HiveConf extends Configuration { "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" + http://git-wip-us.apache.org/repos/asf/hive/blob/c9f56052/itests/hive-unit-hadoop2/src/test/java/org/apache/hadoop/hive/metastore/security/TestHadoopAuthBridge23.java ---------------------------------------------------------------------- diff --git a/itests/hive-unit-hadoop2/src/test/java/org/apache/hadoop/hive/metastore/security/TestHadoopAuthBridge23.java b/itests/hive-unit-hadoop2/src/test/java/org/apache/hadoop/hive/metastore/security/TestHadoopAuthBridge23.java index 14c4e42..cedc933 100644 --- a/itests/hive-unit-hadoop2/src/test/java/org/apache/hadoop/hive/metastore/security/TestHadoopAuthBridge23.java +++ b/itests/hive-unit-hadoop2/src/test/java/org/apache/hadoop/hive/metastore/security/TestHadoopAuthBridge23.java @@ -84,7 +84,7 @@ public class TestHadoopAuthBridge23 { 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(); http://git-wip-us.apache.org/repos/asf/hive/blob/c9f56052/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java ---------------------------------------------------------------------- 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 20e7ec1..f4af6f4 100644 --- a/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java +++ b/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java @@ -7735,7 +7735,8 @@ public class HiveMetaStore extends ThriftHiveMetastore { } 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 MetastoreDelegationTokenManager(); delegationTokenManager.startDelegationTokenSecretManager(conf, baseHandler, http://git-wip-us.apache.org/repos/asf/hive/blob/c9f56052/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java ---------------------------------------------------------------------- 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 541fe5e..0f4a4d8 100644 --- a/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java +++ b/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java @@ -84,7 +84,8 @@ public class HiveAuthFactory { 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(); http://git-wip-us.apache.org/repos/asf/hive/blob/c9f56052/shims/common/src/main/java/org/apache/hadoop/hive/thrift/HadoopThriftAuthBridge.java ---------------------------------------------------------------------- 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 6c8b362..2d39bea 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,11 +98,10 @@ public abstract class HadoopThriftAuthBridge { } } - 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); } - public String getServerPrincipal(String principalConfig, String host) throws IOException { String serverPrincipal = SecurityUtil.getServerPrincipal(principalConfig, host); @@ -309,11 +308,13 @@ public abstract class HadoopThriftAuthBridge { }; 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 +322,7 @@ public abstract class HadoopThriftAuthBridge { /** * 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 +330,24 @@ public abstract class HadoopThriftAuthBridge { 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 +377,7 @@ public abstract class HadoopThriftAuthBridge { TSaslServerTransport.Factory transFactory = createSaslServerTransportFactory(saslProps); - return new TUGIAssumingTransportFactory(transFactory, realUgi); + return new TUGIAssumingTransportFactory(transFactory, clientValidationUGI); } /** @@ -374,7 +389,7 @@ public abstract class HadoopThriftAuthBridge { public TSaslServerTransport.Factory createSaslServerTransportFactory( Map<String, String> 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); http://git-wip-us.apache.org/repos/asf/hive/blob/c9f56052/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/security/HadoopThriftAuthBridge.java ---------------------------------------------------------------------- diff --git a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/security/HadoopThriftAuthBridge.java b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/security/HadoopThriftAuthBridge.java index 3f02ffd..b21b072 100644 --- a/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/security/HadoopThriftAuthBridge.java +++ b/standalone-metastore/src/main/java/org/apache/hadoop/hive/metastore/security/HadoopThriftAuthBridge.java @@ -108,8 +108,8 @@ public abstract class HadoopThriftAuthBridge { } } - 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); } @@ -319,11 +319,13 @@ public abstract class HadoopThriftAuthBridge { }; 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); } @@ -331,7 +333,7 @@ public abstract class HadoopThriftAuthBridge { /** * 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"); @@ -339,10 +341,24 @@ public abstract class HadoopThriftAuthBridge { 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( @@ -372,7 +388,7 @@ public abstract class HadoopThriftAuthBridge { TSaslServerTransport.Factory transFactory = createSaslServerTransportFactory(saslProps); - return new TUGIAssumingTransportFactory(transFactory, realUgi); + return new TUGIAssumingTransportFactory(transFactory, clientValidationUGI); } /** @@ -384,7 +400,7 @@ public abstract class HadoopThriftAuthBridge { public TSaslServerTransport.Factory createSaslServerTransportFactory( Map<String, String> 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);