This is an automated email from the ASF dual-hosted git repository. prasanthj pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/master by this push: new 24313ab HIVE-21783: Avoid authentication for connection from the same domain (Ashutosh Bapat reviewed by Olli Draese, Prasanth Jayachandran) 24313ab is described below commit 24313ab962b2881317bdcb50e67e90d3da3a5cc2 Author: Prasanth Jayachandran <prasan...@apache.org> AuthorDate: Thu Jun 13 01:36:39 2019 -0700 HIVE-21783: Avoid authentication for connection from the same domain (Ashutosh Bapat reviewed by Olli Draese, Prasanth Jayachandran) --- .../java/org/apache/hadoop/hive/conf/HiveConf.java | 8 + .../java/org/apache/hive/minikdc/MiniHiveKdc.java | 23 ++- ...estImproperTrustDomainAuthenticationBinary.java | 28 +++ .../TestImproperTrustDomainAuthenticationHttp.java | 28 +++ .../auth/TestTrustDomainAuthenticationBinary.java | 28 +++ .../auth/TestTrustDomainAuthenticationHttp.java | 28 +++ .../auth/TrustDomainAuthenticationTest.java | 192 +++++++++++++++++++++ .../apache/hive/service/auth/HiveAuthFactory.java | 5 + .../apache/hive/service/auth/PlainSaslHelper.java | 54 ++++++ .../hive/service/cli/thrift/ThriftHttpServlet.java | 53 ++++-- 10 files changed, 422 insertions(+), 25 deletions(-) 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 2cea174..03a8019 100644 --- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java +++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java @@ -3478,6 +3478,14 @@ public class HiveConf extends Configuration { " (Use with property hive.server2.custom.authentication.class)\n" + " PAM: Pluggable authentication module\n" + " NOSASL: Raw transport"), + HIVE_SERVER2_TRUSTED_DOMAIN("hive.server2.trusted.domain", "", + "Specifies the host or a domain to trust connections from. Authentication is skipped " + + "for any connection coming from a host whose hostname ends with the value of this" + + " property. If authentication is expected to be skipped for connections from " + + "only a given host, fully qualified hostname of that host should be specified. By default" + + " it is empty, which means that all the connections to HiveServer2 are authenticated. " + + "When it is non-empty, the client has to provide a Hive user name. Any password, if " + + "provided, will not be used when authentication is skipped."), HIVE_SERVER2_ALLOW_USER_SUBSTITUTION("hive.server2.allow.user.substitution", true, "Allow alternate user to be specified as part of HiveServer2 open connection request."), HIVE_SERVER2_KERBEROS_KEYTAB("hive.server2.authentication.kerberos.keytab", "", diff --git a/itests/hive-minikdc/src/test/java/org/apache/hive/minikdc/MiniHiveKdc.java b/itests/hive-minikdc/src/test/java/org/apache/hive/minikdc/MiniHiveKdc.java index 7d1192a..e604f90 100644 --- a/itests/hive-minikdc/src/test/java/org/apache/hive/minikdc/MiniHiveKdc.java +++ b/itests/hive-minikdc/src/test/java/org/apache/hive/minikdc/MiniHiveKdc.java @@ -36,6 +36,7 @@ import org.apache.hadoop.security.UserGroupInformation; import org.apache.hive.jdbc.miniHS2.MiniHS2; import com.google.common.io.Files; +import org.apache.hive.service.server.HiveServer2; /** * Wrapper around Hadoop's MiniKdc for use in hive tests. @@ -178,15 +179,21 @@ public class MiniHiveKdc { * @return new MiniHS2 instance * @throws Exception */ - public static MiniHS2 getMiniHS2WithKerb(MiniHiveKdc miniHiveKdc, HiveConf hiveConf, + public static MiniHS2 getMiniHS2WithKerb(MiniHiveKdc miniHiveKdc, HiveConf hiveConf, String authType) throws Exception { - String hivePrincipal = - miniHiveKdc.getFullyQualifiedServicePrincipal(MiniHiveKdc.HIVE_SERVICE_PRINCIPAL); - String hiveKeytab = miniHiveKdc.getKeyTabFile( - miniHiveKdc.getServicePrincipalForUser(MiniHiveKdc.HIVE_SERVICE_PRINCIPAL)); - - return new MiniHS2.Builder().withConf(hiveConf).withMiniKdc(hivePrincipal, hiveKeytab). - withAuthenticationType(authType).build(); + String hivePrincipal = + miniHiveKdc.getFullyQualifiedServicePrincipal(MiniHiveKdc.HIVE_SERVICE_PRINCIPAL); + String hiveKeytab = miniHiveKdc.getKeyTabFile( + miniHiveKdc.getServicePrincipalForUser(MiniHiveKdc.HIVE_SERVICE_PRINCIPAL)); + + MiniHS2.Builder miniHS2Builder = new MiniHS2.Builder() + .withConf(hiveConf) + .withMiniKdc(hivePrincipal, hiveKeytab) + .withAuthenticationType(authType); + if (HiveServer2.isHTTPTransportMode(hiveConf)) { + miniHS2Builder.withHTTPTransport(); + } + return miniHS2Builder.build(); } /** diff --git a/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestImproperTrustDomainAuthenticationBinary.java b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestImproperTrustDomainAuthenticationBinary.java new file mode 100644 index 0000000..b7a8bec --- /dev/null +++ b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestImproperTrustDomainAuthenticationBinary.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hive.service.auth; + +import org.junit.BeforeClass; + +public class TestImproperTrustDomainAuthenticationBinary extends TrustDomainAuthenticationTest { + + @BeforeClass + public static void setUp() throws Exception { + initialize(HS2_TRANSPORT_MODE_BINARY, false); + } +} diff --git a/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestImproperTrustDomainAuthenticationHttp.java b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestImproperTrustDomainAuthenticationHttp.java new file mode 100644 index 0000000..57bcf4f --- /dev/null +++ b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestImproperTrustDomainAuthenticationHttp.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hive.service.auth; + +import org.junit.BeforeClass; + +public class TestImproperTrustDomainAuthenticationHttp extends TrustDomainAuthenticationTest { + + @BeforeClass + public static void setUp() throws Exception { + initialize(HS2_TRANSPORT_MODE_HTTP, false); + } +} diff --git a/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestTrustDomainAuthenticationBinary.java b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestTrustDomainAuthenticationBinary.java new file mode 100644 index 0000000..8f6d0b5 --- /dev/null +++ b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestTrustDomainAuthenticationBinary.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hive.service.auth; + +import org.junit.BeforeClass; + +public class TestTrustDomainAuthenticationBinary extends TrustDomainAuthenticationTest { + + @BeforeClass + public static void setUp() throws Exception { + initialize(HS2_TRANSPORT_MODE_BINARY, true); + } +} diff --git a/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestTrustDomainAuthenticationHttp.java b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestTrustDomainAuthenticationHttp.java new file mode 100644 index 0000000..50b195a --- /dev/null +++ b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestTrustDomainAuthenticationHttp.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hive.service.auth; + +import org.junit.BeforeClass; + +public class TestTrustDomainAuthenticationHttp extends TrustDomainAuthenticationTest { + + @BeforeClass + public static void setUp() throws Exception { + initialize(HS2_TRANSPORT_MODE_HTTP, true); + } +} diff --git a/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TrustDomainAuthenticationTest.java b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TrustDomainAuthenticationTest.java new file mode 100644 index 0000000..3eba95c --- /dev/null +++ b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TrustDomainAuthenticationTest.java @@ -0,0 +1,192 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hive.service.auth; + +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hive.service.server.HiveServer2; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.security.sasl.AuthenticationException; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +public class TrustDomainAuthenticationTest { + private static final Logger LOG = LoggerFactory.getLogger(TrustDomainAuthenticationTest.class); + private static HiveServer2 hiveserver2; + private static HiveConf hiveConf; + private static byte[] hiveConfBackup; + private static String correctUser = "hive"; + private static String correctPassword = "passwd"; + private static String wrongPassword = "wrong_password"; + private static String wrongUser = "wrong_user"; + static final String HS2_TRANSPORT_MODE_BINARY = "binary"; + static final String HS2_TRANSPORT_MODE_HTTP = "http"; + private static String hs2TransportMode; + private static boolean properTrustedDomain; + + static void initialize(String transportMode, boolean useProperTrustedDomain) throws Exception { + Assert.assertNotNull(transportMode); + Assert.assertTrue(transportMode.equals(HS2_TRANSPORT_MODE_HTTP) || + transportMode.equals(HS2_TRANSPORT_MODE_BINARY)); + hs2TransportMode = transportMode; + properTrustedDomain = useProperTrustedDomain; + + hiveConf = new HiveConf(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + hiveConf.writeXml(baos); + baos.close(); + hiveConfBackup = baos.toByteArray(); + hiveConf.setVar(HiveConf.ConfVars.HIVE_SERVER2_TRANSPORT_MODE, hs2TransportMode); + hiveConf.setVar(HiveConf.ConfVars.HIVE_SERVER2_AUTHENTICATION, "CUSTOM"); + + // These tests run locally and hence all connections are from localhost. So, when we want to + // test whether trusted domain setting works, use "localhost". When we want to test + // otherwise, use some string other than that. Other authentication tests test empty trusted + // domain so that's not covered under these tests. + hiveConf.setVar(HiveConf.ConfVars.HIVE_SERVER2_TRUSTED_DOMAIN, + properTrustedDomain ? "localhost" : "no_such_domain"); + hiveConf.setVar(HiveConf.ConfVars.HIVE_SERVER2_CUSTOM_AUTHENTICATION_CLASS, + "org.apache.hive.service.auth.TrustDomainAuthenticationTest$SimpleAuthenticationProviderImpl"); + FileOutputStream fos = new FileOutputStream(new File(hiveConf.getHiveSiteLocation().toURI())); + hiveConf.writeXml(fos); + fos.close(); + hiveserver2 = new HiveServer2(); + hiveserver2.init(hiveConf); + hiveserver2.start(); + Thread.sleep(1000); + LOG.info("hiveServer2 start ......"); + } + + @AfterClass + public static void tearDown() throws Exception { + if(hiveConf != null && hiveConfBackup != null) { + FileOutputStream fos = new FileOutputStream(new File(hiveConf.getHiveSiteLocation().toURI())); + fos.write(hiveConfBackup); + fos.close(); + } + if (hiveserver2 != null) { + hiveserver2.stop(); + hiveserver2 = null; + } + Thread.sleep(1000); + LOG.info("hiveServer2 stop ......"); + } + + // TODO: This test doesn't work since getRemoteHost returns IP address instead of a host name + @Test + public void testTrustedDomainAuthentication() throws Exception { + String port = "10000"; + String urlExtra = ""; + if (hs2TransportMode.equals(HS2_TRANSPORT_MODE_HTTP)) { + port = "10001"; + urlExtra = ";transportMode=http;httpPath=cliservice"; + } + + String url = "jdbc:hive2://localhost:" + port + "/default" + urlExtra; + Class.forName("org.apache.hive.jdbc.HiveDriver"); + + if (properTrustedDomain) { + testProperTrustedDomainAuthentication(url); + } else { + testImproperTrustedDomainAuthentication(url); + } + } + + private void testProperTrustedDomainAuthentication(String url) throws SQLException { + // When the connection is from a trusted domain any connection is authentic irrespective of + // user and password + Connection connection = DriverManager.getConnection(url, correctUser, correctPassword); + connection.close(); + + connection = DriverManager.getConnection(url, wrongUser, correctPassword); + connection.close(); + + connection = DriverManager.getConnection(url, wrongUser, wrongPassword); + connection.close(); + + connection = DriverManager.getConnection(url, correctUser, wrongPassword); + connection.close(); + } + + private void testImproperTrustedDomainAuthentication(String url) throws Exception { + // When trusted domain doesn't match requests domain, only the connection with correct user + // and password goes through. + Connection connection = DriverManager.getConnection(url, correctUser, correctPassword); + connection.close(); + + String partErrorMessage = "Peer indicated failure: Error validating the login"; + if (hs2TransportMode.equals(HS2_TRANSPORT_MODE_HTTP)) { + partErrorMessage = "HTTP Response code: 401"; + } + + try (Connection conn = DriverManager.getConnection(url, wrongUser, correctPassword)) { + Assert.fail("Expected Exception"); + } catch (SQLException e) { + Assert.assertNotNull(e.getMessage()); + Assert.assertTrue(e.getMessage(), e.getMessage().contains(partErrorMessage)); + } + + try (Connection conn = DriverManager.getConnection(url, wrongUser, wrongPassword)) { + Assert.fail("Expected Exception"); + } catch (SQLException e) { + Assert.assertNotNull(e.getMessage()); + Assert.assertTrue(e.getMessage(), e.getMessage().contains(partErrorMessage)); + } + + try (Connection conn = DriverManager.getConnection(url, correctUser, wrongPassword)) { + Assert.fail("Expected Exception"); + } catch (SQLException e) { + Assert.assertNotNull(e.getMessage()); + Assert.assertTrue(e.getMessage(), e.getMessage().contains(partErrorMessage)); + } + } + + public static class SimpleAuthenticationProviderImpl implements PasswdAuthenticationProvider { + + private Map<String, String> userMap = new HashMap<String, String>(); + + public SimpleAuthenticationProviderImpl() { + init(); + } + + private void init(){ + userMap.put(correctUser, correctPassword); + } + + @Override + public void Authenticate(String user, String password) throws AuthenticationException { + + if(!userMap.containsKey(user)){ + throw new AuthenticationException("Invalid user : "+user); + } + if(!userMap.get(user).equals(password)){ + throw new AuthenticationException("Invalid passwd : "+password); + } + } + } +} 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 f5f6d49..e07cd7e 100644 --- a/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java +++ b/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java @@ -161,6 +161,11 @@ public class HiveAuthFactory { } else { throw new LoginException("Unsupported authentication type " + authTypeStr); } + + String trustedDomain = HiveConf.getVar(conf, ConfVars.HIVE_SERVER2_TRUSTED_DOMAIN).trim(); + if (!trustedDomain.isEmpty()) { + transportFactory = PlainSaslHelper.getDualPlainTransportFactory(transportFactory, trustedDomain); + } return transportFactory; } diff --git a/service/src/java/org/apache/hive/service/auth/PlainSaslHelper.java b/service/src/java/org/apache/hive/service/auth/PlainSaslHelper.java index 13a1a38..0742311 100644 --- a/service/src/java/org/apache/hive/service/auth/PlainSaslHelper.java +++ b/service/src/java/org/apache/hive/service/auth/PlainSaslHelper.java @@ -18,6 +18,7 @@ package org.apache.hive.service.auth; import java.io.IOException; +import java.net.InetAddress; import java.security.Security; import java.util.HashMap; @@ -39,10 +40,14 @@ import org.apache.thrift.TProcessor; import org.apache.thrift.TProcessorFactory; import org.apache.thrift.transport.TSaslClientTransport; import org.apache.thrift.transport.TSaslServerTransport; +import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public final class PlainSaslHelper { + private static final Logger LOG = LoggerFactory.getLogger(PlainSaslHelper.class); public static TProcessorFactory getPlainProcessorFactory(ThriftCLIService service) { return new SQLPlainProcessorFactory(service); @@ -65,16 +70,65 @@ public final class PlainSaslHelper { return saslFactory; } + static TTransportFactory getDualPlainTransportFactory(TTransportFactory otherTrans, + String trustedDomain) + throws LoginException { + LOG.info("Created additional transport factory for skipping authentication when client " + + "connection is from the same domain."); + return new DualSaslTransportFactory(otherTrans, trustedDomain); + } + public static TTransport getPlainTransport(String username, String password, TTransport underlyingTransport) throws SaslException { return new TSaslClientTransport("PLAIN", null, null, null, new HashMap<String, String>(), new PlainCallbackHandler(username, password), underlyingTransport); } + // Return true if the remote host is from the trusted domain, i.e. host URL has the same + // suffix as the trusted domain. + static public boolean isHostFromTrustedDomain(String remoteHost, String trustedDomain) { + return remoteHost.endsWith(trustedDomain); + } + private PlainSaslHelper() { throw new UnsupportedOperationException("Can't initialize class"); } + static final class DualSaslTransportFactory extends TTransportFactory { + TTransportFactory otherFactory; + TTransportFactory noAuthFactory; + String trustedDomain; + + DualSaslTransportFactory(TTransportFactory otherFactory, String trustedDomain) + throws LoginException { + this.noAuthFactory = getPlainTransportFactory(AuthMethods.NONE.toString()); + this.otherFactory = otherFactory; + this.trustedDomain = trustedDomain; + } + + @Override + public TTransport getTransport(final TTransport trans) { + TSocket tSocket = null; + // Attempt to avoid authentication if only we can fetch the client IP address and it + // happens to be from the same domain as the server. + if (trans instanceof TSocket) { + tSocket = (TSocket) trans; + } else if (trans instanceof TSaslServerTransport) { + TSaslServerTransport saslTrans = (TSaslServerTransport) trans; + tSocket = (TSocket)(saslTrans.getUnderlyingTransport()); + } + String remoteHost = tSocket != null ? + tSocket.getSocket().getInetAddress().getCanonicalHostName() : null; + if (remoteHost != null && isHostFromTrustedDomain(remoteHost, trustedDomain)) { + LOG.info("No authentication performed because the connecting host " + remoteHost + " is " + + "from the trusted domain " + trustedDomain); + return noAuthFactory.getTransport(trans); + } + + return otherFactory.getTransport(trans); + } + } + public static final class PlainServerCallbackHandler implements CallbackHandler { private final AuthMethods authMethod; diff --git a/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpServlet.java b/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpServlet.java index ff8f268..292723e 100644 --- a/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpServlet.java +++ b/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpServlet.java @@ -52,6 +52,7 @@ import org.apache.hive.service.auth.HiveAuthFactory; import org.apache.hive.service.auth.HttpAuthUtils; import org.apache.hive.service.auth.HttpAuthenticationException; import org.apache.hive.service.auth.PasswdAuthenticationProvider; +import org.apache.hive.service.auth.PlainSaslHelper; import org.apache.hive.service.auth.ldap.HttpEmptyAuthenticationException; import org.apache.hive.service.cli.HiveSQLException; import org.apache.hive.service.cli.session.SessionManager; @@ -137,6 +138,9 @@ public class ThriftHttpServlet extends TServlet { return; } } + + clientIpAddress = request.getRemoteAddr(); + LOG.debug("Client IP Address: " + clientIpAddress); // If the cookie based authentication is already enabled, parse the // request and validate the request cookies. if (isCookieAuthEnabled) { @@ -146,25 +150,42 @@ public class ThriftHttpServlet extends TServlet { LOG.info("Could not validate cookie sent, will try to generate a new cookie"); } } - // If the cookie based authentication is not enabled or the request does - // not have a valid cookie, use the kerberos or password based authentication - // depending on the server setup. + // If the cookie based authentication is not enabled or the request does not have a valid + // cookie, use authentication depending on the server setup. if (clientUserName == null) { - // For a kerberos setup - if (isKerberosAuthMode(authType)) { - String delegationToken = request.getHeader(HIVE_DELEGATION_TOKEN_HEADER); - // Each http request must have an Authorization header - if ((delegationToken != null) && (!delegationToken.isEmpty())) { - clientUserName = doTokenAuth(request, response); - } else { - clientUserName = doKerberosAuth(request); + String trustedDomain = HiveConf.getVar(hiveConf, ConfVars.HIVE_SERVER2_TRUSTED_DOMAIN).trim(); + + // Skip authentication if the connection is from the trusted domain, if specified. + // getRemoteHost may or may not return the FQDN of the remote host depending upon the + // HTTP server configuration. So, force a reverse DNS lookup. + String remoteHostName = + InetAddress.getByName(request.getRemoteHost()).getCanonicalHostName(); + if (!trustedDomain.isEmpty() && + PlainSaslHelper.isHostFromTrustedDomain(remoteHostName, trustedDomain)) { + LOG.info("No authentication performed because the connecting host " + remoteHostName + + " is from the trusted domain " + trustedDomain); + // In order to skip authentication, we use auth type NOSASL to be consistent with the + // HiveAuthFactory defaults. In HTTP mode, it will also get us the user name from the + // HTTP request header. + clientUserName = doPasswdAuth(request, HiveAuthConstants.AuthTypes.NOSASL.getAuthName()); + } else { + // For a kerberos setup + if (isKerberosAuthMode(authType)) { + String delegationToken = request.getHeader(HIVE_DELEGATION_TOKEN_HEADER); + // Each http request must have an Authorization header + if ((delegationToken != null) && (!delegationToken.isEmpty())) { + clientUserName = doTokenAuth(request, response); + } else { + clientUserName = doKerberosAuth(request); + } + } + // For password based authentication + else { + clientUserName = doPasswdAuth(request, authType); } - } - // For password based authentication - else { - clientUserName = doPasswdAuth(request, authType); } } + assert (clientUserName != null); LOG.debug("Client username: " + clientUserName); // Set the thread local username to be used for doAs if true @@ -176,8 +197,6 @@ public class ThriftHttpServlet extends TServlet { SessionManager.setProxyUserName(doAsQueryParam); } - clientIpAddress = request.getRemoteAddr(); - LOG.debug("Client IP Address: " + clientIpAddress); // Set the thread local ip address SessionManager.setIpAddress(clientIpAddress);