Skip to content
Draft
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
@@ -1,6 +1,22 @@
package com.clickhouse.client.config;

import java.io.*;
import com.clickhouse.client.ClickHouseConfig;
import com.clickhouse.client.ClickHouseSslContextProvider;
import com.clickhouse.data.ClickHouseUtils;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.KeyManagementException;
import java.security.KeyStore;
Expand All @@ -18,24 +34,30 @@
import java.util.Base64;
import java.util.Optional;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import com.clickhouse.client.ClickHouseConfig;
import com.clickhouse.client.ClickHouseSslContextProvider;
import com.clickhouse.data.ClickHouseUtils;

@Deprecated
public class ClickHouseDefaultSslContextProvider implements ClickHouseSslContextProvider {
static final String PEM_HEADER_PREFIX = "---BEGIN ";
static final String PEM_HEADER_SUFFIX = " PRIVATE KEY---";
static final String PEM_FOOTER_PREFIX = "---END ";

/** Standard PEM encapsulation boundary (RFC 7468). Present in any PEM content, never in a file path. */
static final String PEM_BEGIN_MARKER = "-----BEGIN";

/**
* Opens a stream over PEM material that may be supplied either as a file path (also searched in the home
* directory and on the classpath) or directly as PEM content.
*
* @param certOrContent file path or PEM content of a certificate or a private key
* @return stream over the PEM content
* @throws IOException when the value is a path and the file cannot be opened
*/
static InputStream getCertificateInputStream(String certOrContent) throws IOException {
if (certOrContent.contains(PEM_BEGIN_MARKER)) {
return new ByteArrayInputStream(certOrContent.getBytes(StandardCharsets.US_ASCII));
}
return ClickHouseUtils.getFileInputStream(certOrContent);
}

/**
* An insecure {@link javax.net.ssl.TrustManager}, that don't validate the
* certificate.
Expand Down Expand Up @@ -71,7 +93,7 @@ public static PrivateKey getPrivateKey(String keyFile)
String algorithm = (String) ClickHouseDefaults.SSL_KEY_ALGORITHM.getEffectiveDefaultValue();
StringBuilder builder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(ClickHouseUtils.getFileInputStream(keyFile)))) {
new InputStreamReader(getCertificateInputStream(keyFile)))) {
String line = reader.readLine();
if (line != null) {
algorithm = getAlgorithm(line, algorithm);
Expand Down Expand Up @@ -102,7 +124,7 @@ public KeyStore getKeyStore(String cert, String key) throws NoSuchAlgorithmExcep
ClickHouseUtils.format("%s KeyStore not available", KeyStore.getDefaultType()));
}

try (InputStream in = ClickHouseUtils.getFileInputStream(cert)) {
try (InputStream in = getCertificateInputStream(cert)) {
CertificateFactory factory = CertificateFactory
.getInstance((String) ClickHouseDefaults.SSL_CERTIFICATE_TYPE.getEffectiveDefaultValue());
if (key == null || key.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
package com.clickhouse.client.config;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.PrivateKey;

import com.clickhouse.data.ClickHouseUtils;

import org.testng.Assert;
import org.testng.annotations.Test;

public class ClickHouseDefaultSslContextProviderTest {
static String readTestResource(String name) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (InputStream in = ClickHouseUtils.getFileInputStream(name)) {
byte[] buffer = new byte[2048];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
return new String(out.toByteArray(), StandardCharsets.US_ASCII);
}

@Test(groups = { "unit" })
public void testGetAlgorithm() {
Assert.assertEquals(ClickHouseDefaultSslContextProvider.getAlgorithm("", null), null);
Expand All @@ -19,4 +40,41 @@
// openssl genpkey -out pkey4test.pem -algorithm RSA -pkeyopt rsa_keygen_bits:2048
Assert.assertNotNull(ClickHouseDefaultSslContextProvider.getPrivateKey("pkey4test.pem"));
}

@Test(groups = { "unit" })
public void testGetCertificateInputStream() throws Exception {
String pemContent = readTestResource("client.crt");
try (InputStream in = ClickHouseDefaultSslContextProvider.getCertificateInputStream(pemContent)) {

Check warning on line 47 in clickhouse-client/src/test/java/com/clickhouse/client/config/ClickHouseDefaultSslContextProviderTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "ClickHouseDefaultSslContextProvider"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ608VFschQzNLXlEKnz&open=AZ608VFschQzNLXlEKnz&pullRequest=2873
byte[] buffer = new byte[pemContent.length()];
int read = in.read(buffer);
Assert.assertEquals(new String(buffer, 0, read, StandardCharsets.US_ASCII), pemContent);
}

try (InputStream in = ClickHouseDefaultSslContextProvider.getCertificateInputStream("client.crt")) {

Check warning on line 53 in clickhouse-client/src/test/java/com/clickhouse/client/config/ClickHouseDefaultSslContextProviderTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "ClickHouseDefaultSslContextProvider"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ608VFschQzNLXlEKn0&open=AZ608VFschQzNLXlEKn0&pullRequest=2873
Assert.assertTrue(in.read() != -1);
}

Assert.assertThrows(FileNotFoundException.class,
() -> ClickHouseDefaultSslContextProvider.getCertificateInputStream("non-existent.crt"));

Check warning on line 58 in clickhouse-client/src/test/java/com/clickhouse/client/config/ClickHouseDefaultSslContextProviderTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "ClickHouseDefaultSslContextProvider"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ608VFschQzNLXlEKn1&open=AZ608VFschQzNLXlEKn1&pullRequest=2873
}

@Test(groups = { "unit" })
public void testGetPrivateKeyFromPemContent() throws Exception {
PrivateKey fromFile = ClickHouseDefaultSslContextProvider.getPrivateKey("pkey4test.pem");

Check warning on line 63 in clickhouse-client/src/test/java/com/clickhouse/client/config/ClickHouseDefaultSslContextProviderTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "ClickHouseDefaultSslContextProvider"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ608VFschQzNLXlEKn2&open=AZ608VFschQzNLXlEKn2&pullRequest=2873
PrivateKey fromContent = ClickHouseDefaultSslContextProvider

Check warning on line 64 in clickhouse-client/src/test/java/com/clickhouse/client/config/ClickHouseDefaultSslContextProviderTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "ClickHouseDefaultSslContextProvider"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ608VFschQzNLXlEKn3&open=AZ608VFschQzNLXlEKn3&pullRequest=2873
.getPrivateKey(readTestResource("pkey4test.pem"));
Assert.assertEquals(fromContent, fromFile);
}

@Test(groups = { "unit" })
public void testGetKeyStoreFromPemContent() throws Exception {
ClickHouseDefaultSslContextProvider provider = new ClickHouseDefaultSslContextProvider();

Check warning on line 71 in clickhouse-client/src/test/java/com/clickhouse/client/config/ClickHouseDefaultSslContextProviderTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "ClickHouseDefaultSslContextProvider"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ608VFschQzNLXlEKn4&open=AZ608VFschQzNLXlEKn4&pullRequest=2873

Check warning on line 71 in clickhouse-client/src/test/java/com/clickhouse/client/config/ClickHouseDefaultSslContextProviderTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "ClickHouseDefaultSslContextProvider"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ608VFschQzNLXlEKn5&open=AZ608VFschQzNLXlEKn5&pullRequest=2873

KeyStore trustStore = provider.getKeyStore(readTestResource("client.crt"), null);
Assert.assertNotNull(trustStore.getCertificate("cert1"));

KeyStore keyStore = provider.getKeyStore(readTestResource("some_user.crt"),
readTestResource("some_user.key"));
Assert.assertNotNull(keyStore.getKey("key", null));
}
}
12 changes: 12 additions & 0 deletions client-v2/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,18 @@
<version>1.5.7-6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.84</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
<version>1.84</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.clickhouse.client.api.internal;

import com.clickhouse.client.ClickHouseSslContextProvider;
import com.clickhouse.client.api.ClickHouseException;
import com.clickhouse.client.api.Client;
import com.clickhouse.client.api.ClientConfigProperties;
Expand All @@ -14,6 +13,7 @@
import com.clickhouse.client.api.enums.ProxyType;
import com.clickhouse.client.api.http.ClickHouseHttpProto;
import com.clickhouse.client.api.transport.Endpoint;
import com.clickhouse.client.config.ClickHouseDefaultSslContextProvider;
import com.clickhouse.data.ClickHouseFormat;
import net.jpountz.lz4.LZ4Factory;
import org.apache.commons.compress.compressors.CompressorStreamFactory;
Expand Down Expand Up @@ -131,6 +131,8 @@

LZ4Factory lz4Factory;

private final ClickHouseDefaultSslContextProvider sslContextProvider = new ClickHouseDefaultSslContextProvider();

Check warning on line 134 in client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "ClickHouseDefaultSslContextProvider"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ608VHichQzNLXlEKn7&open=AZ608VHichQzNLXlEKn7&pullRequest=2873

Check warning on line 134 in client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "ClickHouseDefaultSslContextProvider"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ608VHichQzNLXlEKn6&open=AZ608VHichQzNLXlEKn6&pullRequest=2873

public HttpAPIClientHelper(Map<String, Object> configuration, Object metricsRegistry, boolean initSslContext, LZ4Factory lz4Factory) {
this.metricsRegistry = metricsRegistry;
this.httpClient = createHttpClient(initSslContext, configuration);
Expand Down Expand Up @@ -163,8 +165,10 @@
} catch (NoSuchAlgorithmException e) {
throw new ClientException("Failed to create default SSL context", e);
}
ClickHouseSslContextProvider sslContextProvider = ClickHouseSslContextProvider.getProvider();
String trustStorePath = (String) configuration.get(ClientConfigProperties.SSL_TRUST_STORE.getKey());
final String trustStorePath = (String) configuration.get(ClientConfigProperties.SSL_TRUST_STORE.getKey());
final String caCertificate = (String) configuration.get(ClientConfigProperties.CA_CERTIFICATE.getKey());
final String sslCertificate = (String) configuration.get(ClientConfigProperties.SSL_CERTIFICATE.getKey());
final String sslKey = (String) configuration.get(ClientConfigProperties.SSL_KEY.getKey());
if (trustStorePath != null) {
try {
sslContext = sslContextProvider.getSslContextFromKeyStore(
Expand All @@ -175,16 +179,9 @@
} catch (SSLException e) {
throw new ClientMisconfigurationException("Failed to create SSL context from a keystore", e);
}
} else if (configuration.get(ClientConfigProperties.CA_CERTIFICATE.getKey()) != null ||
configuration.get(ClientConfigProperties.SSL_CERTIFICATE.getKey()) != null ||
configuration.get(ClientConfigProperties.SSL_KEY.getKey()) != null) {

} else if (caCertificate != null || sslCertificate != null|| sslKey != null) {
try {
sslContext = sslContextProvider.getSslContextFromCerts(
(String) configuration.get(ClientConfigProperties.SSL_CERTIFICATE.getKey()),
(String) configuration.get(ClientConfigProperties.SSL_KEY.getKey()),
(String) configuration.get(ClientConfigProperties.CA_CERTIFICATE.getKey())
);
sslContext = sslContextProvider.getSslContextFromCerts(sslCertificate, sslKey, caCertificate);
} catch (SSLException e) {
throw new ClientMisconfigurationException("Failed to create SSL context from certificates", e);
}
Expand Down
Loading
Loading