Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,13 @@ public class ClientOptions

@Option(name = "--truststore-type", title = "truststore type", description = "Truststore type")
public String trustStoreType = KeyStore.getDefaultType();

@Option(name = "--access-token", title = "access token", description = "Access token")
public String accessToken;

@Option(name = "--insecure", title = "trust all certificates", description = "Skip validation of HTTP server certificates (should only be used for debugging)")
public boolean insecure;

@Option(name = "--user", title = "user", description = "Username")
public String user = System.getProperty("user.name");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ public boolean run()
Optional.ofNullable(clientOptions.truststorePassword),
Optional.ofNullable(clientOptions.trustStoreType),
Optional.ofNullable(clientOptions.accessToken),
clientOptions.insecure,
Optional.ofNullable(clientOptions.user),
clientOptions.password ? Optional.of(getPassword()) : Optional.empty(),
Optional.ofNullable(clientOptions.krb5Principal),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package com.facebook.presto.cli;

import com.facebook.presto.client.ClientSession;
import com.facebook.presto.client.OkHttpUtil;
import com.facebook.presto.client.StatementClient;
import com.google.common.net.HostAndPort;
import okhttp3.OkHttpClient;
Expand Down Expand Up @@ -63,6 +64,7 @@ public QueryRunner(
Optional<String> truststorePassword,
Optional<String> trustStoreType,
Optional<String> accessToken,
boolean insecureSsl,
Optional<String> user,
Optional<String> password,
Optional<String> kerberosPrincipal,
Expand All @@ -77,7 +79,12 @@ public QueryRunner(
this.debug = debug;
this.runtime = runtime;

this.sslSetup = builder -> setupSsl(builder, keystorePath, keystorePassword, keyStoreType, truststorePath, truststorePassword, trustStoreType);
if (insecureSsl) {
this.sslSetup = OkHttpUtil::setupInsecureSsl;
}
else {
this.sslSetup = builder -> setupSsl(builder, keystorePath, keystorePassword, keyStoreType, truststorePath, truststorePassword, trustStoreType);
}

OkHttpClient.Builder builder = new OkHttpClient.Builder();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,19 @@ protected MockResponse createMockResponse()

protected void executeQueries(List<String> queries)
{
Console console = new Console();
QueryRunner queryRunner = createQueryRunner(createMockClientSession());
executeQueries(queryRunner, queries);
}

protected void executeQueries(QueryRunner queryRunner, List<String> queries)
{
Console console = new Console();
for (String query : queries) {
console.executeCommand(queryRunner, query, CSV, false);
}
}

protected static QueryRunner createQueryRunner(ClientSession clientSession)
protected static QueryRunner createQueryRunner(ClientSession clientSession, boolean insecureSsl)
{
return new QueryRunner(
clientSession,
Expand All @@ -136,6 +141,7 @@ protected static QueryRunner createQueryRunner(ClientSession clientSession)
Optional.empty(),
Optional.empty(),
Optional.empty(),
insecureSsl,
Optional.empty(),
Optional.empty(),
Optional.empty(),
Expand All @@ -147,6 +153,11 @@ protected static QueryRunner createQueryRunner(ClientSession clientSession)
true);
}

protected static QueryRunner createQueryRunner(ClientSession clientSession)
{
return createQueryRunner(clientSession, false);
}

protected static void assertHeaders(String headerName, Headers headers, Set<String> expectedSessionHeaderValues)
{
assertEquals(ImmutableSet.copyOf(headers.values(headerName)), expectedSessionHeaderValues);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Licensed 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 com.facebook.presto.cli;

import com.google.common.collect.ImmutableList;
import okhttp3.mockwebserver.MockWebServer;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import static com.google.common.io.Resources.getResource;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.testng.Assert.assertEquals;

@Test(singleThreaded = true)
public class TestInsecureQueryRunner
extends AbstractCliTest
{
@Override
@BeforeMethod
public void setup()
throws IOException
{
server = new MockWebServer();
SSLContext sslContext = buildTestSslContext();
server.useHttps(sslContext.getSocketFactory(), false);
server.start();
}

@Override
@AfterMethod(alwaysRun = true)
public void teardown()
throws IOException
{
server.close();
}

@Test
public void testInsecureConnection()
{
server.enqueue(createMockResponse());
server.enqueue(createMockResponse());
executeQueries(createQueryRunner(createMockClientSession(), true),
ImmutableList.of("query with insecure mode;"));
try {
assertEquals(server.takeRequest(1, SECONDS).getPath(), "/v1/statement");
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}

private SSLContext buildTestSslContext()
throws IOException
{
try {
// Load self-signed certificate
char[] serverKeyStorePassword = "insecure-ssl-test".toCharArray();
KeyStore serverKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
try (InputStream in = getResource(getClass(), "/insecure-ssl-test.jks").openStream()) {
serverKeyStore.load(in, serverKeyStorePassword);
}
String kmfAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlgorithm);
kmf.init(serverKeyStore, serverKeyStorePassword);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(kmfAlgorithm);
trustManagerFactory.init(serverKeyStore);
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
return sslContext;
}
catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException | KeyManagementException e) {
throw new IOException("failed to initialize SSL context", e);
}
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import java.net.Proxy;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
Expand Down Expand Up @@ -138,6 +139,41 @@ private static InetSocketAddress toUnresolvedAddress(HostAndPort address)
return InetSocketAddress.createUnresolved(address.getHost(), address.getPort());
}

public static void setupInsecureSsl(OkHttpClient.Builder clientBuilder)
{
try {
X509TrustManager trustAllCerts = new X509TrustManager()
{
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
{
throw new UnsupportedOperationException("checkClientTrusted should not be called");
}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
{
// skip validation of server certificate
}

@Override
public X509Certificate[] getAcceptedIssuers()
{
return new X509Certificate[0];
}
};

SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[] {trustAllCerts}, new SecureRandom());

clientBuilder.sslSocketFactory(sslContext.getSocketFactory(), trustAllCerts);
clientBuilder.hostnameVerifier((hostname, session) -> true);
}
catch (GeneralSecurityException e) {
throw new ClientException("Error setting up SSL: " + e.getMessage(), e);
}
}

public static void setupSsl(
OkHttpClient.Builder clientBuilder,
Optional<String> keyStorePath,
Expand Down
46 changes: 35 additions & 11 deletions presto-docs/src/main/sphinx/clients/presto-cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,19 @@ Run the CLI with the ``--help`` option to see the online help.

./presto --help

NAME
presto - Presto interactive console

SYNOPSIS
presto [--access-token <access token>] [--catalog <catalog>]
[--client-info <client-info>]
[--client-request-timeout <client request timeout>]
[--client-tags <client tags>] [--debug] [--disable-compression]
[--execute <execute>] [--extra-credential <extra-credential>...]
[(-f <file> | --file <file>)] [(-h | --help)]
[--http-proxy <http-proxy>] [--ignore-errors]
[--keystore-password <keystore password>]
[--keystore-path <keystore path>]
[--disable-redirects] [--execute <execute>]
[--extra-credential <extra-credential>...] [(-f <file> | --file <file>)]
[(-h | --help)] [--http-proxy <http-proxy>] [--ignore-errors]
[--insecure] [--keystore-password <keystore password>]
[--keystore-path <keystore path>] [--keystore-type <keystore type>]
[--krb5-config-path <krb5 config path>]
[--krb5-credential-cache-path <krb5 credential cache path>]
[--krb5-disable-remote-service-hostname-canonicalization]
Expand All @@ -90,10 +93,12 @@ SYNOPSIS
[--krb5-remote-service-name <krb5 remote service name>]
[--log-levels-file <log levels file>] [--output-format <output-format>]
[--password] [--resource-estimate <resource-estimate>...]
[--schema <schema>] [--server <server>] [--session <session>...]
[--socks-proxy <socks-proxy>] [--source <source>]
[--truststore-password <truststore password>]
[--truststore-path <truststore path>] [--user <user>] [--version]
[--runtime-stats] [--schema <schema>] [--server <server>]
[--session <session>...] [--socks-proxy <socks-proxy>]
[--source <source>] [--truststore-password <truststore password>]
[--truststore-path <truststore path>]
[--truststore-type <truststore type>] [--user <user>]
[--validate-nexturi-source] [--version]

OPTIONS
--access-token <access token>
Expand All @@ -117,6 +122,9 @@ OPTIONS
--disable-compression
Disable compression of query results

--disable-redirects
Disable client following redirects from server

--execute <execute>
Execute specified statements and exit

Expand All @@ -137,12 +145,19 @@ OPTIONS
Continue processing in batch mode when an error occurs (default is
to exit immediately)

--insecure
Skip validation of HTTP server certificates (should only be used for
debugging)

--keystore-password <keystore password>
Keystore password

--keystore-path <keystore path>
Keystore path

--keystore-type <keystore type>
Keystore type

--krb5-config-path <krb5 config path>
Kerberos config file path (default: /etc/krb5.conf)

Expand All @@ -166,7 +181,7 @@ OPTIONS
Configure log levels for debugging using this file

--output-format <output-format>
Output format for batch mode [ALIGNED, VERTICAL, CSV, TSV,
Output format for batch mode [ALIGNED, VERTICAL, JSON, CSV, TSV,
CSV_HEADER, TSV_HEADER, NULL] (default: CSV)

--password
Expand All @@ -177,7 +192,8 @@ OPTIONS
key=value)

--runtime-stats
Enable runtime stats information. Flag must be used in conjunction with the --debug flag
Enable runtime stats information. Flag must be used in conjunction
with the --debug flag

--schema <schema>
Default schema
Expand All @@ -201,8 +217,16 @@ OPTIONS
--truststore-path <truststore path>
Truststore path

--truststore-type <truststore type>
Truststore type

--user <user>
Username

--validate-nexturi-source
Validate nextUri server host and port does not change during query
execution

--version
Display version information and exit