diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java index 218225ede208..5446df272d74 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java @@ -205,6 +205,8 @@ public class BigQueryConnection extends BigQueryNoOpsConnection { boolean filterTablesOnDefaultDataset; String sslTrustStorePath; String sslTrustStorePassword; + String sslTrustStoreType; + String sslTrustStoreProvider; long maxBytesBilled; Map labels; Integer httpConnectTimeout; @@ -277,6 +279,8 @@ public class BigQueryConnection extends BigQueryNoOpsConnection { this.sslTrustStorePath = ds.getSSLTrustStorePath(); this.sslTrustStorePassword = ds.getSSLTrustStorePassword(); + this.sslTrustStoreType = ds.getSSLTrustStoreType(); + this.sslTrustStoreProvider = ds.getSSLTrustStoreProvider(); this.httpConnectTimeout = ds.getHttpConnectTimeout(); this.httpReadTimeout = ds.getHttpReadTimeout(); @@ -285,6 +289,8 @@ public class BigQueryConnection extends BigQueryNoOpsConnection { proxyProperties, this.sslTrustStorePath, this.sslTrustStorePassword, + this.sslTrustStoreType, + this.sslTrustStoreProvider, this.httpConnectTimeout, this.httpReadTimeout, this.connectionClassName); @@ -337,6 +343,8 @@ public class BigQueryConnection extends BigQueryNoOpsConnection { proxyProperties, this.sslTrustStorePath, this.sslTrustStorePassword, + this.sslTrustStoreType, + this.sslTrustStoreProvider, this.connectionClassName); this.enableSession = ds.getEnableSession(); this.unsupportedHTAPIFallback = ds.getUnsupportedHTAPIFallback(); diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcProxyUtility.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcProxyUtility.java index 983eda9760f8..7f16047e0dff 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcProxyUtility.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcProxyUtility.java @@ -130,6 +130,8 @@ static HttpTransportOptions getHttpTransportOptions( Map proxyProperties, String sslTrustStorePath, String sslTrustStorePassword, + String sslTrustStoreType, + String sslTrustStoreProvider, Integer connectTimeout, Integer readTimeout, String callerClassName) { @@ -143,7 +145,12 @@ static HttpTransportOptions getHttpTransportOptions( if (hasProxyOrSsl) { httpTransportOptionsBuilder.setHttpTransportFactory( getHttpTransportFactory( - proxyProperties, sslTrustStorePath, sslTrustStorePassword, callerClassName)); + proxyProperties, + sslTrustStorePath, + sslTrustStorePassword, + sslTrustStoreType, + sslTrustStoreProvider, + callerClassName)); } else { httpTransportOptionsBuilder.setHttpTransportFactory(() -> DEFAULT_TRANSPORT); } @@ -162,6 +169,8 @@ private static HttpTransportFactory getHttpTransportFactory( Map proxyProperties, String sslTrustStorePath, String sslTrustStorePassword, + String sslTrustStoreType, + String sslTrustStoreProvider, String callerClassName) { LOG.finest("++enter++\t" + callerClassName); HttpClientBuilder httpClientBuilder = HttpClients.custom(); @@ -182,7 +191,7 @@ private static HttpTransportFactory getHttpTransportFactory( if (sslTrustStorePath != null) { try (FileInputStream trustStoreStream = new FileInputStream(sslTrustStorePath)) { - KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + KeyStore trustStore = loadKeyStore(sslTrustStoreType, sslTrustStoreProvider); char[] trustStorePasswordChars = sslTrustStorePassword != null ? sslTrustStorePassword.toCharArray() : null; trustStore.load(trustStoreStream, trustStorePasswordChars); @@ -243,6 +252,8 @@ static TransportChannelProvider getTransportChannelProvider( Map proxyProperties, String sslTrustStorePath, String sslTrustStorePassword, + String sslTrustStoreType, + String sslTrustStoreProvider, String callerClassName) { LOG.finest("++enter++\t" + callerClassName); boolean hasProxy = proxyProperties.containsKey(BigQueryJdbcUrlUtility.PROXY_HOST_PROPERTY_NAME); @@ -271,7 +282,7 @@ public ProxiedSocketAddress proxyFor(SocketAddress socketAddress) { instanceof io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder) { try (FileInputStream trustStoreStream = new FileInputStream(sslTrustStorePath)) { - KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + KeyStore trustStore = loadKeyStore(sslTrustStoreType, sslTrustStoreProvider); char[] trustStorePasswordChars = sslTrustStorePassword != null ? sslTrustStorePassword.toCharArray() @@ -300,6 +311,15 @@ public ProxiedSocketAddress proxyFor(SocketAddress socketAddress) { return transportChannelProvider; } + private static KeyStore loadKeyStore(String type, String provider) + throws GeneralSecurityException { + String resolvedType = + (type != null && !type.trim().isEmpty()) ? type.trim() : KeyStore.getDefaultType(); + return (provider != null && !provider.trim().isEmpty()) + ? KeyStore.getInstance(resolvedType, provider.trim()) + : KeyStore.getInstance(resolvedType); + } + private static HttpConnectProxiedSocketAddress getHttpConnectProxiedSocketAddress( InetSocketAddress socketAddress, Map proxyProperties) { String proxyHost = proxyProperties.get(BigQueryJdbcUrlUtility.PROXY_HOST_PROPERTY_NAME); diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcUrlUtility.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcUrlUtility.java index a46a4eecd4f7..481df4abf35f 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcUrlUtility.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcUrlUtility.java @@ -22,6 +22,7 @@ import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.net.UrlEscapers; +import java.security.KeyStore; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -173,6 +174,8 @@ protected boolean removeEldestEntry(Map.Entry> eldes static final String REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME = "RequestGoogleDriveScope"; static final String SSL_TRUST_STORE_PROPERTY_NAME = "SSLTrustStore"; static final String SSL_TRUST_STORE_PWD_PROPERTY_NAME = "SSLTrustStorePwd"; + static final String SSL_TRUST_STORE_TYPE_PROPERTY_NAME = "SSLTrustStoreType"; + static final String SSL_TRUST_STORE_PROVIDER_PROPERTY_NAME = "SSLTrustStoreProvider"; static final int DEFAULT_REQUEST_GOOGLE_DRIVE_SCOPE_VALUE = 0; static final String MAX_BYTES_BILLED_PROPERTY_NAME = "MaximumBytesBilled"; static final Long DEFAULT_MAX_BYTES_BILLED_VALUE = 0L; @@ -607,6 +610,17 @@ protected boolean removeEldestEntry(Map.Entry> eldes "The password for accessing the Java TrustStore that is specified using" + " the property SSLTrustStore.") .build(), + BigQueryConnectionProperty.newBuilder() + .setName(SSL_TRUST_STORE_TYPE_PROPERTY_NAME) + .setDescription( + "The type of the Java TrustStore specified using the property SSLTrustStore.") + .setLazyDefaultValue(KeyStore::getDefaultType) + .build(), + BigQueryConnectionProperty.newBuilder() + .setName(SSL_TRUST_STORE_PROVIDER_PROPERTY_NAME) + .setDescription( + "The security provider of the Java TrustStore specified using the property SSLTrustStore.") + .build(), BigQueryConnectionProperty.newBuilder() .setName(HTTP_CONNECT_TIMEOUT_PROPERTY_NAME) .setDescription( diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/DataSource.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/DataSource.java index e51ebeb00e90..f6489d33dd37 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/DataSource.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/DataSource.java @@ -89,6 +89,8 @@ public class DataSource implements javax.sql.DataSource { private Integer metadataFetchThreadCount; private String sslTrustStorePath; private String sslTrustStorePassword; + private String sslTrustStoreType; + private String sslTrustStoreProvider; private Map labels; private String requestReason; private Integer timeout; @@ -261,6 +263,12 @@ public class DataSource implements javax.sql.DataSource { .put( BigQueryJdbcUrlUtility.SSL_TRUST_STORE_PWD_PROPERTY_NAME, DataSource::setSSLTrustStorePassword) + .put( + BigQueryJdbcUrlUtility.SSL_TRUST_STORE_TYPE_PROPERTY_NAME, + DataSource::setSSLTrustStoreType) + .put( + BigQueryJdbcUrlUtility.SSL_TRUST_STORE_PROVIDER_PROPERTY_NAME, + DataSource::setSSLTrustStoreProvider) .put( BigQueryJdbcUrlUtility.LABELS_PROPERTY_NAME, (ds, val) -> @@ -588,6 +596,15 @@ Properties createProperties() { BigQueryJdbcUrlUtility.SSL_TRUST_STORE_PWD_PROPERTY_NAME, String.valueOf(this.sslTrustStorePassword)); } + if (this.sslTrustStoreType != null) { + connectionProperties.setProperty( + BigQueryJdbcUrlUtility.SSL_TRUST_STORE_TYPE_PROPERTY_NAME, this.sslTrustStoreType); + } + if (this.sslTrustStoreProvider != null) { + connectionProperties.setProperty( + BigQueryJdbcUrlUtility.SSL_TRUST_STORE_PROVIDER_PROPERTY_NAME, + this.sslTrustStoreProvider); + } if (this.labels != null) { connectionProperties.setProperty( BigQueryJdbcUrlUtility.LABELS_PROPERTY_NAME, serializeMap(this.labels)); @@ -1124,6 +1141,22 @@ public void setSSLTrustStorePassword(String sslTrustStorePassword) { this.sslTrustStorePassword = sslTrustStorePassword; } + public String getSSLTrustStoreType() { + return sslTrustStoreType; + } + + public void setSSLTrustStoreType(String sslTrustStoreType) { + this.sslTrustStoreType = sslTrustStoreType; + } + + public String getSSLTrustStoreProvider() { + return sslTrustStoreProvider; + } + + public void setSSLTrustStoreProvider(String sslTrustStoreProvider) { + this.sslTrustStoreProvider = sslTrustStoreProvider; + } + public Map getLabels() { return labels; } diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcProxyUtilityTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcProxyUtilityTest.java index c8e613f08941..a3fd2536b0bd 100644 --- a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcProxyUtilityTest.java +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcProxyUtilityTest.java @@ -139,7 +139,7 @@ public void testGetHttpTransportOptionsWithAuthenticatedProxy() { BigQueryJdbcProxyUtility.parseProxyProperties(connection_uri, null); HttpTransportOptions result = BigQueryJdbcProxyUtility.getHttpTransportOptions( - proxyProperties, null, null, null, null, "TestClass"); + proxyProperties, null, null, null, null, null, null, "TestClass"); assertNotNull(result); } @@ -156,7 +156,7 @@ public void testGetHttpTransportOptionsWithNonAuthenticatedProxy() { BigQueryJdbcProxyUtility.parseProxyProperties(connection_uri, null); HttpTransportOptions result = BigQueryJdbcProxyUtility.getHttpTransportOptions( - proxyProperties, null, null, null, null, "TestClass"); + proxyProperties, null, null, null, null, null, null, "TestClass"); assertNotNull(result); } @@ -171,7 +171,7 @@ public void testGetHttpTransportOptionsWithNoProxySettingsReturnsDefaultOptions( BigQueryJdbcProxyUtility.parseProxyProperties(connection_uri, null); HttpTransportOptions result = BigQueryJdbcProxyUtility.getHttpTransportOptions( - proxyProperties, null, null, null, null, "TestClass"); + proxyProperties, null, null, null, null, null, null, "TestClass"); assertNotNull(result); assertNotNull(result.getHttpTransportFactory()); } @@ -189,7 +189,14 @@ public void testGetHttpTransportOptions_withSslTrustStore_noPassword() throws Ex String trustStorePath = getTestResourcePath("test_truststore_nopass.jks"); HttpTransportOptions options = BigQueryJdbcProxyUtility.getHttpTransportOptions( - Collections.emptyMap(), trustStorePath, null, null, null, "TestClass"); + Collections.emptyMap(), + trustStorePath, + null, + null, + null, + null, + null, + "TestClass"); assertNotNull(options); assertNotNull(options.getHttpTransportFactory()); } @@ -204,6 +211,8 @@ public void testGetHttpTransportOptions_withSslTrustStore_withCorrectPassword() "testpassword", null, null, + null, + null, "TestClass"); assertNotNull(options); assertNotNull(options.getHttpTransportFactory()); @@ -223,6 +232,8 @@ public void testGetHttpTransportOptions_withSslTrustStore_withIncorrectPassword( "wrongpassword", null, null, + null, + null, "TestClass")); assertThat(exception.getCause()).isInstanceOf(IOException.class); } @@ -240,6 +251,8 @@ public void testGetHttpTransportOptions_withInvalidSslTrustStorePath() { null, null, null, + null, + null, "TestClass")); assertThat(exception.getCause()).isInstanceOf(FileNotFoundException.class); @@ -254,7 +267,7 @@ public void testGetHttpTransportOptions_withSslAndProxy() throws Exception { HttpTransportOptions options = BigQueryJdbcProxyUtility.getHttpTransportOptions( - proxyProperties, trustStorePath, null, null, null, "TestClass"); + proxyProperties, trustStorePath, null, null, null, null, null, "TestClass"); assertNotNull(options); assertNotNull(options.getHttpTransportFactory()); } @@ -264,7 +277,7 @@ public void testGetTransportChannelProvider_withSslTrustStore_noPassword() throw String trustStorePath = getTestResourcePath("test_truststore_nopass.jks"); TransportChannelProvider provider = BigQueryJdbcProxyUtility.getTransportChannelProvider( - Collections.emptyMap(), trustStorePath, null, "TestClass"); + Collections.emptyMap(), trustStorePath, null, null, null, "TestClass"); assertNotNull(provider); } @@ -274,7 +287,12 @@ public void testGetTransportChannelProvider_withSslTrustStore_withCorrectPasswor String trustStorePath = getTestResourcePath("test_truststore_withpass.jks"); TransportChannelProvider provider = BigQueryJdbcProxyUtility.getTransportChannelProvider( - Collections.emptyMap(), trustStorePath, "testpassword", "TestClass"); + Collections.emptyMap(), + trustStorePath, + "testpassword", + null, + null, + "TestClass"); assertNotNull(provider); } @@ -287,7 +305,7 @@ public void testGetTransportChannelProvider_withSslAndProxy() throws Exception { TransportChannelProvider provider = BigQueryJdbcProxyUtility.getTransportChannelProvider( - proxyProperties, trustStorePath, null, "TestClass"); + proxyProperties, trustStorePath, null, null, null, "TestClass"); assertNotNull(provider); } @@ -295,7 +313,7 @@ public void testGetTransportChannelProvider_withSslAndProxy() throws Exception { public void testGetTransportChannelProvider_noProxyNoSsl_returnsNull() { TransportChannelProvider provider = BigQueryJdbcProxyUtility.getTransportChannelProvider( - Collections.emptyMap(), null, null, "TestClass"); + Collections.emptyMap(), null, null, null, null, "TestClass"); assertNull(provider); } @@ -303,7 +321,14 @@ public void testGetTransportChannelProvider_noProxyNoSsl_returnsNull() { public void testGetHttpTransportOptions_noProxyNoSsl_returnsDefaultOptions() { HttpTransportOptions options = BigQueryJdbcProxyUtility.getHttpTransportOptions( - Collections.emptyMap(), null, null, null, null, "TestClass"); + Collections.emptyMap(), + null, + null, + null, + null, + null, + null, + "TestClass"); assertNotNull(options); assertNotNull(options.getHttpTransportFactory()); } @@ -312,7 +337,14 @@ public void testGetHttpTransportOptions_noProxyNoSsl_returnsDefaultOptions() { public void testGetHttpTransportOptions_withTimeouts_returnsOptions() { HttpTransportOptions options = BigQueryJdbcProxyUtility.getHttpTransportOptions( - Collections.emptyMap(), null, null, 10000, 20000, "TestClass"); + Collections.emptyMap(), + null, + null, + null, + null, + 10000, + 20000, + "TestClass"); assertNotNull(options); assertThat(options.getConnectTimeout()).isEqualTo(10000); assertThat(options.getReadTimeout()).isEqualTo(20000); @@ -322,7 +354,14 @@ public void testGetHttpTransportOptions_withTimeouts_returnsOptions() { public void testGetHttpTransportOptions_withConnectTimeoutOnly_returnsOptions() { HttpTransportOptions options = BigQueryJdbcProxyUtility.getHttpTransportOptions( - Collections.emptyMap(), null, null, 10000, null, "TestClass"); + Collections.emptyMap(), + null, + null, + null, + null, + 10000, + null, + "TestClass"); assertNotNull(options); assertThat(options.getConnectTimeout()).isEqualTo(10000); // readTimeout defaults to HttpTransport's internal default, not asserted here. @@ -332,9 +371,52 @@ public void testGetHttpTransportOptions_withConnectTimeoutOnly_returnsOptions() public void testGetHttpTransportOptions_withReadTimeoutOnly_returnsOptions() { HttpTransportOptions options = BigQueryJdbcProxyUtility.getHttpTransportOptions( - Collections.emptyMap(), null, null, null, 20000, "TestClass"); + Collections.emptyMap(), + null, + null, + null, + null, + null, + 20000, + "TestClass"); assertNotNull(options); assertThat(options.getReadTimeout()).isEqualTo(20000); // connectTimeout defaults to HttpTransport's internal default, not asserted here. } + + @Test + public void testGetHttpTransportOptions_withSslTrustStore_withCustomType() throws Exception { + String trustStorePath = getTestResourcePath("test_truststore_nopass.jks"); + HttpTransportOptions options = + BigQueryJdbcProxyUtility.getHttpTransportOptions( + Collections.emptyMap(), + trustStorePath, + null, + "JKS", + null, + null, + null, + "TestClass"); + assertNotNull(options); + assertNotNull(options.getHttpTransportFactory()); + } + + @Test + public void testGetHttpTransportOptions_withSslTrustStore_withInvalidProvider() throws Exception { + String trustStorePath = getTestResourcePath("test_truststore_nopass.jks"); + BigQueryJdbcRuntimeException exception = + assertThrows( + BigQueryJdbcRuntimeException.class, + () -> + BigQueryJdbcProxyUtility.getHttpTransportOptions( + Collections.emptyMap(), + trustStorePath, + null, + "JKS", + "FakeProvider", + null, + null, + "TestClass")); + assertThat(exception.getCause()).isInstanceOf(java.security.NoSuchProviderException.class); + } } diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITLocalSslValidationTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITLocalSslValidationTest.java index 6ccffb703547..722d01b9fc79 100644 --- a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITLocalSslValidationTest.java +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITLocalSslValidationTest.java @@ -181,7 +181,9 @@ public static void tearDown() { mockServer.stop(); } - private ProcessResult runSubprocess(String trustStore, String password) throws Exception { + private ProcessResult runSubprocess( + String trustStore, String password, boolean useSystemProperties, String type) + throws Exception { String javaHome = System.getProperty("java.home"); String javaBin = javaHome + File.separator + "bin" + File.separator + "java"; String classpath = System.getProperty("java.class.path"); @@ -189,17 +191,25 @@ private ProcessResult runSubprocess(String trustStore, String password) throws E List command = new ArrayList<>(); command.add(javaBin); - if (trustStore != null) { - command.add("-Djavax.net.ssl.trustStore=" + trustStore); - } - if (password != null) { - command.add("-Djavax.net.ssl.trustStorePassword=" + password); + if (useSystemProperties) { + if (trustStore != null) { + command.add("-Djavax.net.ssl.trustStore=" + trustStore); + } + if (password != null) { + command.add("-Djavax.net.ssl.trustStorePassword=" + password); + } } command.add("-cp"); command.add(classpath); command.add(className); command.add(String.valueOf(port)); + if (!useSystemProperties) { + command.add(trustStore != null ? trustStore : ""); + command.add(password != null ? password : ""); + command.add(type != null ? type : ""); + } + ProcessBuilder builder = new ProcessBuilder(command); builder.redirectErrorStream(true); Process process = builder.start(); @@ -226,20 +236,34 @@ private ProcessResult runSubprocess(String trustStore, String password) throws E @Test public void testDefaultSslFailsForSelfSigned() throws Exception { - ProcessResult result = runSubprocess(null, null); + ProcessResult result = runSubprocess(null, null, true, null); assertEquals(1, result.exitCode, "Subprocess should fail. Output:\n" + result.stdout); assertTrue(result.stdout.contains(PKIX_ERROR_MSG)); } - @Test - public void testCustomTrustStoreSucceeds() throws Exception { + private String getTrustStorePath() throws Exception { URL trustStoreUrl = getClass().getResource(TRUSTSTORE_RESOURCE); if (trustStoreUrl == null) { throw new IllegalStateException( "Truststore resource " + TRUSTSTORE_RESOURCE + " not found on classpath!"); } - String trustStorePath = new File(trustStoreUrl.toURI()).getAbsolutePath(); - ProcessResult result = runSubprocess(trustStorePath, PASSWORD); + return new File(trustStoreUrl.toURI()).getAbsolutePath(); + } + + @Test + public void testCustomTrustStoreSucceeds() throws Exception { + ProcessResult result = runSubprocess(getTrustStorePath(), PASSWORD, true, null); + + assertEquals(0, result.exitCode, "Subprocess failed. Output:\n" + result.stdout); + assertTrue(result.stdout.contains(SUCCESS_MARKER)); + assertFalse( + result.stdout.contains(PKIX_ERROR_MSG), + "Handshake failed with SSL error: " + result.stdout); + } + + @Test + public void testCustomTrustStorePropertiesSucceeds() throws Exception { + ProcessResult result = runSubprocess(getTrustStorePath(), PASSWORD, false, "JKS"); assertEquals(0, result.exitCode, "Subprocess failed. Output:\n" + result.stdout); assertTrue(result.stdout.contains(SUCCESS_MARKER)); @@ -251,13 +275,24 @@ public void testCustomTrustStoreSucceeds() throws Exception { public static void main(String[] args) { int port = Integer.parseInt(args[0]); String baseUri = "jdbc:bigquery://https://" + HOST + ":" + port + ";"; - String url = + URIBuilder uriBuilder = new URIBuilder(baseUri) .append("EndpointOverrides", "BIGQUERY=https://" + HOST + ":" + port) .append("ProjectId", "dummy") .append("OAuthType", 2) - .append("OAuthAccessToken", "dummy-token") - .toString(); + .append("OAuthAccessToken", "dummy-token"); + + if (args.length > 1 && !args[1].isEmpty()) { + uriBuilder.append("SSLTrustStore", args[1]); + } + if (args.length > 2 && !args[2].isEmpty()) { + uriBuilder.append("SSLTrustStorePwd", args[2]); + } + if (args.length > 3 && !args[3].isEmpty()) { + uriBuilder.append("SSLTrustStoreType", args[3]); + } + + String url = uriBuilder.toString(); try (Connection connection = DriverManager.getConnection(url); Statement statement = connection.createStatement()) { statement.execute("SELECT 1");