Skip to content

Commit

Permalink
Merge pull request apache#648 from ashutosh-bapat/hive21783
Browse files Browse the repository at this point in the history
HIVE-21783: Accept Hive connections from the same domain without authentication.
  • Loading branch information
prasanthj authored Jun 16, 2019
2 parents 67240e7 + b386328 commit 56fc46b
Show file tree
Hide file tree
Showing 10 changed files with 422 additions and 25 deletions.
8 changes: 8 additions & 0 deletions common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
Original file line number Diff line number Diff line change
Expand Up @@ -3478,6 +3478,14 @@ public static enum ConfVars {
" (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", "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
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.
Expand Down Expand Up @@ -178,15 +179,21 @@ public static MiniHS2 getMiniHS2WithKerb(MiniHiveKdc miniHiveKdc, HiveConf hiveC
* @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();
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ public TTransportFactory getAuthTransFactory() throws LoginException {
} 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;
}

Expand Down
Loading

0 comments on commit 56fc46b

Please sign in to comment.