Package org.apache.hive.jdbc

Source Code of org.apache.hive.jdbc.TestSSL

/**
* 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.jdbc;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.io.File;
import java.net.URLEncoder;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.util.Shell;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
import org.apache.hive.jdbc.miniHS2.MiniHS2;
import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestSSL {
  private static final Logger LOG = LoggerFactory.getLogger(TestSSL.class);
  private static final String KEY_STORE_NAME = "keystore.jks";
  private static final String TRUST_STORE_NAME = "truststore.jks";
  private static final String KEY_STORE_PASSWORD = "HiveJdbc";
  private static final String JAVA_TRUST_STORE_PROP = "javax.net.ssl.trustStore";
  private static final String JAVA_TRUST_STORE_PASS_PROP = "javax.net.ssl.trustStorePassword";
  private static final String HS2_BINARY_MODE = "binary";
  private static final String HS2_HTTP_MODE = "http";
  private static final String HS2_HTTP_ENDPOINT = "cliservice";
  private static final String HS2_BINARY_AUTH_MODE = "NONE";
  private static final String HS2_HTTP_AUTH_MODE = "NOSASL";

  private MiniHS2 miniHS2 = null;
  private static HiveConf conf = new HiveConf();
  private Connection hs2Conn = null;
  private String dataFileDir = conf.get("test.data.files");
  private Map<String, String> confOverlay;
  private final String SSL_CONN_PARAMS = ";ssl=true;sslTrustStore=" + URLEncoder.encode(dataFileDir + File.separator +
      TRUST_STORE_NAME) + ";trustStorePassword=" + KEY_STORE_PASSWORD;

  @BeforeClass
  public static void beforeTest() throws Exception {
    Class.forName(MiniHS2.getJdbcDriverName());
  }

  @Before
  public void setUp() throws Exception {
    DriverManager.setLoginTimeout(0);
    if (!System.getProperty("test.data.files", "").isEmpty()) {
      dataFileDir = System.getProperty("test.data.files");
    }
    dataFileDir = dataFileDir.replace('\\', '/').replace("c:", "");
    miniHS2 = new MiniHS2(conf);
    confOverlay = new HashMap<String, String>();
  }

  @After
  public void tearDown() throws Exception {
    if (hs2Conn != null) {
      hs2Conn.close();
    }
    if (miniHS2 != null && miniHS2.isStarted()) {
      miniHS2.stop();
    }
    System.clearProperty(JAVA_TRUST_STORE_PROP);
    System.clearProperty(JAVA_TRUST_STORE_PASS_PROP);
  }

  private int execCommand(String cmd) throws Exception {
    int exitCode;
    try {
      String output = Shell.execCommand("bash", "-c", cmd);
      LOG.info("Output from '" + cmd + "': " + output) ;
      exitCode = 0;
    } catch (Shell.ExitCodeException e) {
      exitCode = e.getExitCode();
      LOG.info("Error executing '" + cmd + "', exitCode = " + exitCode, e);
    }
    return exitCode;
  }

  /***
   * Tests to ensure SSLv2 and SSLv3 are disabled
   */
  @Test
  public void testSSLVersion() throws Exception {
    Assume.assumeTrue(execCommand("which openssl") == 0); // we need openssl
    Assume.assumeTrue(System.getProperty("os.name").toLowerCase()
      .contains("linux")); // we depend on linux openssl exit codes

    setSslConfOverlay(confOverlay);
    // Test in binary mode
    setBinaryConfOverlay(confOverlay);
    // Start HS2 with SSL
    miniHS2.start(confOverlay);

    // make SSL connection
    hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL() + ";ssl=true;sslTrustStore=" +
        dataFileDir + File.separator + TRUST_STORE_NAME + ";trustStorePassword=" +
        KEY_STORE_PASSWORD, System.getProperty("user.name"), "bar");
    hs2Conn.close();
    Assert.assertEquals("Expected exit code of 1", 1,
      execCommand("openssl s_client -connect " + miniHS2.getHost() + ":" + miniHS2.getBinaryPort()
      + " -ssl2 < /dev/null"));
    Assert.assertEquals("Expected exit code of 1", 1,
      execCommand("openssl s_client -connect " + miniHS2.getHost() + ":" + miniHS2.getBinaryPort()
      + " -ssl3 < /dev/null"));
    miniHS2.stop();

    // Test in http mode
    setHttpConfOverlay(confOverlay);
    miniHS2.start(confOverlay);
    // make SSL connection
    try {
      hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL() +
          ";ssl=true;sslTrustStore=" + dataFileDir + File.separator +
          TRUST_STORE_NAME + ";trustStorePassword=" + KEY_STORE_PASSWORD +
          "?hive.server2.transport.mode=" + HS2_HTTP_MODE +
          ";hive.server2.thrift.http.path=" + HS2_HTTP_ENDPOINT,
          System.getProperty("user.name"), "bar");
      Assert.fail("Expected SQLException during connect");
    } catch (SQLException e) {
      LOG.info("Expected exception: " + e, e);
      Assert.assertEquals("08S01", e.getSQLState().trim());
      Throwable cause = e.getCause();
      Assert.assertNotNull(cause);
      while (cause.getCause() != null) {
        cause = cause.getCause();
      }
      Assert.assertEquals("org.apache.http.NoHttpResponseException", cause.getClass().getName());
      Assert.assertEquals("The target server failed to respond", cause.getMessage());
    }
    miniHS2.stop();
  }

  /***
   * Test SSL client with non-SSL server fails
   * @throws Exception
   */
  @Test
  public void testInvalidConfig() throws Exception {
    clearSslConfOverlay(confOverlay);
    // Test in binary mode
    setBinaryConfOverlay(confOverlay);
    miniHS2.start(confOverlay);
    DriverManager.setLoginTimeout(4);
    try {
      hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL("default", SSL_CONN_PARAMS),
          System.getProperty("user.name"), "bar");
      fail("SSL connection should fail with NON-SSL server");
    } catch (SQLException e) {
      // expected error
      assertEquals("08S01", e.getSQLState().trim());
    }

    System.setProperty(JAVA_TRUST_STORE_PROP, dataFileDir + File.separator + TRUST_STORE_NAME );
    System.setProperty(JAVA_TRUST_STORE_PASS_PROP, KEY_STORE_PASSWORD);
    try {
      hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL() + ";ssl=true",
          System.getProperty("user.name"), "bar");
      fail("SSL connection should fail with NON-SSL server");
    } catch (SQLException e) {
      // expected error
      assertEquals("08S01", e.getSQLState().trim());
    }
    miniHS2.stop();

    // Test in http mode with ssl properties specified in url
    System.clearProperty(JAVA_TRUST_STORE_PROP);
    System.clearProperty(JAVA_TRUST_STORE_PASS_PROP);
    setHttpConfOverlay(confOverlay);
    miniHS2.start(confOverlay);
    try {
      hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL("default", SSL_CONN_PARAMS),
          System.getProperty("user.name"), "bar");
      fail("SSL connection should fail with NON-SSL server");
    } catch (SQLException e) {
      // expected error
      assertEquals("08S01", e.getSQLState().trim());
    }
  }


  /***
   * Test non-SSL client with SSL server fails
   * @throws Exception
   */
  @Test
  public void testConnectionMismatch() throws Exception {
    setSslConfOverlay(confOverlay);
    // Test in binary mode
    setBinaryConfOverlay(confOverlay);
    miniHS2.start(confOverlay);
    // Start HS2 with SSL
    try {
      hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL(), System.getProperty("user.name"), "bar");
      fail("NON SSL connection should fail with SSL server");
    } catch (SQLException e) {
      // expected error
      assertEquals("08S01", e.getSQLState().trim());
    }

    try {
      hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL()+ ";ssl=false",
          System.getProperty("user.name"), "bar");
      fail("NON SSL connection should fail with SSL server");
    } catch (SQLException e) {
      // expected error
      assertEquals("08S01", e.getSQLState().trim());
    }
    miniHS2.stop();

    // Test in http mode
    setHttpConfOverlay(confOverlay);
    miniHS2.start(confOverlay);
    try {
      hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL("default", ";ssl=false"),
          System.getProperty("user.name"), "bar");
      fail("NON SSL connection should fail with SSL server");
    } catch (SQLException e) {
      // expected error
      assertEquals("08S01", e.getSQLState().trim());
    }

  }

  /***
   * Test SSL client connection to SSL server
   * @throws Exception
   */
  @Test
  public void testSSLConnectionWithURL() throws Exception {
    setSslConfOverlay(confOverlay);
    // Test in binary mode
    setBinaryConfOverlay(confOverlay);
    // Start HS2 with SSL
    miniHS2.start(confOverlay);

    // make SSL connection
    hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL("default", SSL_CONN_PARAMS),
        System.getProperty("user.name"), "bar");
    hs2Conn.close();
    miniHS2.stop();

    // Test in http mode
    setHttpConfOverlay(confOverlay);
    miniHS2.start(confOverlay);
    // make SSL connection
    hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL("default", SSL_CONN_PARAMS),
        System.getProperty("user.name"), "bar");
    hs2Conn.close();
  }

  /***
   * Test SSL client connection to SSL server
   * @throws Exception
   */
  @Test
  public void testSSLConnectionWithProperty() throws Exception {
    setSslConfOverlay(confOverlay);
    // Test in binary mode
    setBinaryConfOverlay(confOverlay);
    // Start HS2 with SSL
    miniHS2.start(confOverlay);

    System.setProperty(JAVA_TRUST_STORE_PROP, dataFileDir + File.separator + TRUST_STORE_NAME );
    System.setProperty(JAVA_TRUST_STORE_PASS_PROP, KEY_STORE_PASSWORD);
    // make SSL connection
    hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL() + ";ssl=true",
        System.getProperty("user.name"), "bar");
    hs2Conn.close();
    miniHS2.stop();

    // Test in http mode
    setHttpConfOverlay(confOverlay);
    miniHS2.start(confOverlay);
    // make SSL connection
    hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL("default", SSL_CONN_PARAMS),
        System.getProperty("user.name"), "bar");
    hs2Conn.close();
  }

  /**
   * Start HS2 in SSL mode, open a SSL connection and fetch data
   * @throws Exception
   */
  @Test
  public void testSSLFetch() throws Exception {
    setSslConfOverlay(confOverlay);
    // Test in binary mode
    setBinaryConfOverlay(confOverlay);
    // Start HS2 with SSL
    miniHS2.start(confOverlay);

    String tableName = "sslTab";
    Path dataFilePath = new Path(dataFileDir, "kv1.txt");

    // make SSL connection
    hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL("default", SSL_CONN_PARAMS),
        System.getProperty("user.name"), "bar");

    // Set up test data
    setupTestTableWithData(tableName, dataFilePath, hs2Conn);

    Statement stmt = hs2Conn.createStatement();
    ResultSet res = stmt.executeQuery("SELECT * FROM " + tableName);
    int rowCount = 0;
    while (res.next()) {
      ++rowCount;
      assertEquals("val_" + res.getInt(1), res.getString(2));
    }
    // read result over SSL
    assertEquals(500, rowCount);

    hs2Conn.close();
  }

  /**
   * Start HS2 in Http mode with SSL enabled, open a SSL connection and fetch data
   * @throws Exception
   */
  @Test
  public void testSSLFetchHttp() throws Exception {
    setSslConfOverlay(confOverlay);
    // Test in http mode
    setHttpConfOverlay(confOverlay);
    miniHS2.start(confOverlay);

    String tableName = "sslTab";
    Path dataFilePath = new Path(dataFileDir, "kv1.txt");

    // make SSL connection
    hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL("default", SSL_CONN_PARAMS),
        System.getProperty("user.name"), "bar");

    // Set up test data
    setupTestTableWithData(tableName, dataFilePath, hs2Conn);
    Statement stmt = hs2Conn.createStatement();
    ResultSet res = stmt.executeQuery("SELECT * FROM " + tableName);
    int rowCount = 0;
    while (res.next()) {
      ++rowCount;
      assertEquals("val_" + res.getInt(1), res.getString(2));
    }
    // read result over SSL
    assertEquals(500, rowCount);

    hs2Conn.close();
  }

  private void setupTestTableWithData(String tableName, Path dataFilePath,
      Connection hs2Conn) throws Exception {
    Statement stmt = hs2Conn.createStatement();
    stmt.execute("set hive.support.concurrency = false");

    stmt.execute("drop table if exists " + tableName);
    stmt.execute("create table " + tableName
        + " (under_col int comment 'the under column', value string)");

    // load data
    stmt.execute("load data local inpath '"
        + dataFilePath.toString() + "' into table " + tableName);
    stmt.close();
  }

  private void setSslConfOverlay(Map<String, String> confOverlay) {
    confOverlay.put(ConfVars.HIVE_SERVER2_USE_SSL.varname, "true");
    confOverlay.put(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH.varname,
        dataFileDir + File.separator +  KEY_STORE_NAME);
    confOverlay.put(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PASSWORD.varname,
        KEY_STORE_PASSWORD);
  }

  private void clearSslConfOverlay(Map<String, String> confOverlay) {
    confOverlay.put(ConfVars.HIVE_SERVER2_USE_SSL.varname, "false");
  }

  // Currently http mode works with server in NOSASL auth mode & doesn't support doAs
  private void setHttpConfOverlay(Map<String, String> confOverlay) {
    confOverlay.put(ConfVars.HIVE_SERVER2_TRANSPORT_MODE.varname, HS2_HTTP_MODE);
    confOverlay.put(ConfVars.HIVE_SERVER2_THRIFT_HTTP_PATH.varname, HS2_HTTP_ENDPOINT);
    confOverlay.put(ConfVars.HIVE_SERVER2_AUTHENTICATION.varname,  HS2_HTTP_AUTH_MODE);
    confOverlay.put(ConfVars.HIVE_SERVER2_ENABLE_DOAS.varname, "false");
  }

  private void setBinaryConfOverlay(Map<String, String> confOverlay) {
    confOverlay.put(ConfVars.HIVE_SERVER2_TRANSPORT_MODE.varname, HS2_BINARY_MODE);
    confOverlay.put(ConfVars.HIVE_SERVER2_AUTHENTICATION.varname,  HS2_BINARY_AUTH_MODE);
    confOverlay.put(ConfVars.HIVE_SERVER2_ENABLE_DOAS.varname, "true");
  }
}
TOP

Related Classes of org.apache.hive.jdbc.TestSSL

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.