Skip to content

Commit 9e53b41

Browse files
authored
Merge pull request #1753 from ClickHouse/feat_support_https
[client-v2] Https Support
2 parents f40f778 + 2ede016 commit 9e53b41

File tree

7 files changed

+248
-43
lines changed

7 files changed

+248
-43
lines changed

.github/workflows/build.yml

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ jobs:
4141
name: Compile using JDK 8
4242
steps:
4343
- name: Check out repository
44-
uses: actions/checkout@v3
44+
uses: actions/checkout@v4
4545
- name: Check out PR
4646
run: |
4747
git fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 \
4848
origin pull/${{ github.event.inputs.pr }}/merge:merged-pr && git checkout merged-pr
4949
if: github.event.inputs.pr != ''
5050
- name: Install JDK 8 and Maven
51-
uses: actions/setup-java@v3
51+
uses: actions/setup-java@v4
5252
with:
5353
distribution: "temurin"
5454
java-version: 8
@@ -60,6 +60,14 @@ jobs:
6060
export LIB_VER=$(grep '<revision>' pom.xml | sed -e 's|[[:space:]]*<[/]*revision>[[:space:]]*||g')
6161
find `pwd`/examples -type f -name pom.xml -exec sed -i -e "s|\(<clickhouse-java.version>\).*\(<\)|\1$LIB_VER\2|g" {} \;
6262
for d in $(ls -d `pwd`/examples/*/); do cd $d && mvn --batch-mode --no-transfer-progress clean compile; done
63+
- name: Upload test results
64+
uses: actions/upload-artifact@v4
65+
if: failure()
66+
with:
67+
name: result ${{ github.job }}
68+
path: |
69+
**/target/failsafe-reports
70+
**/target/surefire-reports
6371
6472
test-multi-env:
6573
needs: compile
@@ -77,22 +85,22 @@ jobs:
7785
name: ${{ matrix.dist }} JDK 17 on ${{ matrix.os }}
7886
steps:
7987
- name: Check out repository
80-
uses: actions/checkout@v3
88+
uses: actions/checkout@v4
8189
- name: Check out PR
8290
run: |
8391
git fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 \
8492
origin pull/${{ github.event.inputs.pr }}/merge:merged-pr && git checkout merged-pr
8593
if: github.event.inputs.pr != ''
8694
- name: Install JDK 17 and Maven
87-
uses: actions/setup-java@v3
95+
uses: actions/setup-java@v4
8896
with:
8997
distribution: ${{ matrix.dist }}
9098
java-version: 17
9199
cache: "maven"
92100
- name: Test libraries
93101
run: mvn --batch-mode --no-transfer-progress -Dj8 -DskipITs verify
94102
- name: Upload test results
95-
uses: actions/upload-artifact@v2
103+
uses: actions/upload-artifact@v4
96104
if: failure()
97105
with:
98106
name: result ${{ github.job }}
@@ -107,7 +115,7 @@ jobs:
107115
name: Test Native Image
108116
steps:
109117
- name: Check out repository
110-
uses: actions/checkout@v3
118+
uses: actions/checkout@v4
111119
- name: Check out PR
112120
run: |
113121
git fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 \
@@ -140,14 +148,14 @@ jobs:
140148
name: CLI client + CH LTS
141149
steps:
142150
- name: Check out repository
143-
uses: actions/checkout@v3
151+
uses: actions/checkout@v4
144152
- name: Check out PR
145153
run: |
146154
git fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 \
147155
origin pull/${{ github.event.inputs.pr }}/merge:merged-pr && git checkout merged-pr
148156
if: github.event.inputs.pr != ''
149157
- name: Install JDK 8 and Maven
150-
uses: actions/setup-java@v3
158+
uses: actions/setup-java@v4
151159
with:
152160
distribution: "temurin"
153161
java-version: 8
@@ -164,7 +172,7 @@ jobs:
164172
run: |
165173
mvn --also-make --batch-mode --no-transfer-progress --projects clickhouse-cli-client -DclickhouseVersion=$PREFERRED_LTS_VERSION -Dj8 -DskipUTs verify
166174
- name: Upload test results
167-
uses: actions/upload-artifact@v2
175+
uses: actions/upload-artifact@v4
168176
if: failure()
169177
with:
170178
name: result ${{ github.job }}
@@ -185,14 +193,14 @@ jobs:
185193
name: Java client + CH ${{ matrix.clickhouse }}
186194
steps:
187195
- name: Check out repository
188-
uses: actions/checkout@v3
196+
uses: actions/checkout@v4
189197
- name: Check out PR
190198
run: |
191199
git fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 \
192200
origin pull/${{ github.event.inputs.pr }}/merge:merged-pr && git checkout merged-pr
193201
if: github.event.inputs.pr != ''
194202
- name: Install JDK 17 and Maven
195-
uses: actions/setup-java@v3
203+
uses: actions/setup-java@v4
196204
with:
197205
distribution: "temurin"
198206
java-version: |
@@ -224,7 +232,7 @@ jobs:
224232
run: |
225233
mvn --also-make --batch-mode --no-transfer-progress --projects clickhouse-cli-client,clickhouse-grpc-client,clickhouse-http-client -DclickhouseVersion=${{ matrix.clickhouse }} verify
226234
- name: Upload test results
227-
uses: actions/upload-artifact@v2
235+
uses: actions/upload-artifact@v4
228236
if: failure()
229237
with:
230238
name: result ${{ github.job }}
@@ -306,14 +314,14 @@ jobs:
306314
name: JDBC driver + CH ${{ matrix.clickhouse }} (${{ matrix.protocol }})
307315
steps:
308316
- name: Check out repository
309-
uses: actions/checkout@v3
317+
uses: actions/checkout@v4
310318
- name: Check out PR
311319
run: |
312320
git fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 \
313321
origin pull/${{ github.event.inputs.pr }}/merge:merged-pr && git checkout merged-pr
314322
if: github.event.inputs.pr != ''
315323
- name: Install JDK 17 and Maven
316-
uses: actions/setup-java@v3
324+
uses: actions/setup-java@v4
317325
with:
318326
distribution: "temurin"
319327
java-version: |
@@ -347,7 +355,7 @@ jobs:
347355
run: |
348356
mvn --batch-mode --no-transfer-progress --projects clickhouse-jdbc -DclickhouseVersion=${{ matrix.clickhouse }} -Dprotocol=${{ matrix.protocol }} verify
349357
- name: Upload test results
350-
uses: actions/upload-artifact@v2
358+
uses: actions/upload-artifact@v4
351359
if: failure()
352360
with:
353361
name: result ${{ github.job }}
@@ -369,14 +377,14 @@ jobs:
369377
name: R2DBC ${{ matrix.r2dbc }} + CH ${{ matrix.clickhouse }} (${{ matrix.protocol }})
370378
steps:
371379
- name: Check out repository
372-
uses: actions/checkout@v3
380+
uses: actions/checkout@v4
373381
- name: Check out PR
374382
run: |
375383
git fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 \
376384
origin pull/${{ github.event.inputs.pr }}/merge:merged-pr && git checkout merged-pr
377385
if: github.event.inputs.pr != ''
378386
- name: Install JDK 17 and Maven
379-
uses: actions/setup-java@v3
387+
uses: actions/setup-java@v4
380388
with:
381389
distribution: "temurin"
382390
java-version: |
@@ -408,7 +416,7 @@ jobs:
408416
mvn --batch-mode --no-transfer-progress --projects clickhouse-r2dbc -DclickhouseVersion=${{ matrix.clickhouse }} \
409417
-D'r2dbc-spi.version=${{ matrix.r2dbc }}' -Dprotocol=${{ matrix.protocol }} verify
410418
- name: Upload test results
411-
uses: actions/upload-artifact@v2
419+
uses: actions/upload-artifact@v4
412420
if: failure()
413421
with:
414422
name: result ${{ github.job }}
@@ -442,14 +450,14 @@ jobs:
442450
name: "TimeZone(C/S): ${{ matrix.clientTz }} vs. ${{ matrix.serverTz }}"
443451
steps:
444452
- name: Check out repository
445-
uses: actions/checkout@v3
453+
uses: actions/checkout@v4
446454
- name: Check out PR
447455
run: |
448456
git fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 \
449457
origin pull/${{ github.event.inputs.pr }}/merge:merged-pr && git checkout merged-pr
450458
if: github.event.inputs.pr != ''
451459
- name: Install JDK 8 and Maven
452-
uses: actions/setup-java@v3
460+
uses: actions/setup-java@v4
453461
with:
454462
distribution: "temurin"
455463
java-version: 8
@@ -462,7 +470,7 @@ jobs:
462470
-DclickhouseTimezone=${{ matrix.serverTz }} -Duser.timezone=${{ matrix.clientTz }} \
463471
-Dj8 -DskipUTs verify
464472
- name: Upload test results
465-
uses: actions/upload-artifact@v2
473+
uses: actions/upload-artifact@v4
466474
if: failure()
467475
with:
468476
name: result ${{ github.job }}

clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseSslContextProvider.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package com.clickhouse.client;
22

3+
import java.security.KeyStore;
34
import java.util.Optional;
45
import java.util.ServiceLoader;
56

7+
import javax.net.ssl.SSLContext;
68
import javax.net.ssl.SSLException;
79

10+
import com.clickhouse.client.config.ClickHouseSslMode;
811
import com.clickhouse.data.ClickHouseChecker;
912

1013
/**
@@ -44,4 +47,26 @@ static ClickHouseSslContextProvider getProvider() {
4447
* @throws SSLException when error occured getting SSL context
4548
*/
4649
<T> Optional<T> getSslContext(Class<? extends T> sslContextClass, ClickHouseConfig config) throws SSLException;
50+
51+
/**
52+
* Use this method if trust store should be imported
53+
*
54+
* @param clientCert
55+
* @param clientKey
56+
* @param sslRootCert
57+
* @return
58+
* @throws SSLException
59+
*/
60+
SSLContext getSslContextFromCerts(String clientCert, String clientKey, String sslRootCert) throws SSLException;
61+
62+
/**
63+
* Use this method if client has separate certs
64+
*
65+
* @param truststorePath
66+
* @param truststorePassword
67+
* @param keyStoreType
68+
* @return
69+
* @throws SSLException
70+
*/
71+
SSLContext getSslContextFromKeyStore(String truststorePath, String truststorePassword, String keyStoreType) throws SSLException;
4772
}

clickhouse-client/src/main/java/com/clickhouse/client/config/ClickHouseDefaultSslContextProvider.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ static String getAlgorithm(String header, String defaultAlg) {
6565
return startIndex < endIndex ? header.substring(startIndex, endIndex) : defaultAlg;
6666
}
6767

68-
static PrivateKey getPrivateKey(String keyFile)
68+
public static PrivateKey getPrivateKey(String keyFile)
6969
throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
7070
String algorithm = (String) ClickHouseDefaults.SSL_KEY_ALGORITHM.getEffectiveDefaultValue();
7171
StringBuilder builder = new StringBuilder();
@@ -90,7 +90,7 @@ static PrivateKey getPrivateKey(String keyFile)
9090
return kf.generatePrivate(keySpec);
9191
}
9292

93-
protected KeyStore getKeyStore(String cert, String key) throws NoSuchAlgorithmException, InvalidKeySpecException,
93+
public KeyStore getKeyStore(String cert, String key) throws NoSuchAlgorithmException, InvalidKeySpecException,
9494
IOException, CertificateException, KeyStoreException {
9595
final KeyStore ks;
9696
try {
@@ -117,7 +117,7 @@ protected KeyStore getKeyStore(String cert, String key) throws NoSuchAlgorithmEx
117117
return ks;
118118
}
119119

120-
protected SSLContext getJavaSslContext(ClickHouseConfig config) throws SSLException {
120+
public SSLContext getJavaSslContext(ClickHouseConfig config) throws SSLException {
121121
ClickHouseSslMode sslMode = config.getSslMode();
122122
String clientCert = config.getSslCert();
123123
String clientKey = config.getSslKey();
@@ -126,6 +126,20 @@ protected SSLContext getJavaSslContext(ClickHouseConfig config) throws SSLExcept
126126
String truststorePassword = config.getTrustStorePassword();
127127
String keyStoreType = (!config.getKeyStoreType().isEmpty() && config.getKeyStoreType() != null) ? config.getKeyStoreType() : KeyStore.getDefaultType();
128128

129+
return getSslContextImpl(sslMode, clientCert, clientKey, sslRootCert, truststorePath, truststorePassword,
130+
keyStoreType);
131+
}
132+
133+
public SSLContext getSslContextFromCerts(String clientCert, String clientKey, String sslRootCert) throws SSLException {
134+
return getSslContextImpl(ClickHouseSslMode.STRICT,
135+
clientCert, clientKey, sslRootCert, null, null, KeyStore.getDefaultType());
136+
}
137+
138+
public SSLContext getSslContextFromKeyStore(String truststorePath, String truststorePassword, String keyStoreType) throws SSLException {
139+
return getSslContextImpl(ClickHouseSslMode.STRICT, null, null, null, truststorePath, truststorePassword, keyStoreType);
140+
}
141+
142+
private SSLContext getSslContextImpl(ClickHouseSslMode sslMode, String clientCert, String clientKey, String sslRootCert, String truststorePath, String truststorePassword, String keyStoreType) throws SSLException {
129143
SSLContext ctx;
130144
try {
131145
ctx = SSLContext.getInstance((String) ClickHouseDefaults.SSL_PROTOCOL.getEffectiveDefaultValue());

clickhouse-http-client/src/main/java/com/clickhouse/client/http/ClickHouseHttpProto.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ public class ClickHouseHttpProto {
3939
*/
4040
public static final String HEADER_DATABASE = "X-ClickHouse-Database";
4141

42+
/**
43+
* Name of user to be used to authenticate
44+
*/
45+
public static final String HEADER_DB_USER = "X-ClickHouse-User";
46+
47+
public static final String HEADER_DB_PASSWORD = "X-ClickHouse-Key";
48+
4249
/**
4350
* Query parameter to specify the query ID.
4451
*/

client-v2/src/main/java/com/clickhouse/client/api/Client.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,75 @@ public Builder setHttpCookiesEnabled(boolean enabled) {
459459
return this;
460460
}
461461

462+
463+
/**
464+
* Defines path to the trust store file. It cannot be combined with
465+
* certificates. Either trust store or certificates should be used.
466+
*
467+
* {@see setSSLTrustStorePassword} and {@see setSSLTrustStoreType}
468+
* @param path
469+
* @return
470+
*/
471+
public Builder setSSLTrustStore(String path) {
472+
this.configuration.put(ClickHouseClientOption.TRUST_STORE.getKey(), path);
473+
return this;
474+
}
475+
476+
/**
477+
* Password for the SSL Trust Store.
478+
*
479+
* @param password
480+
* @return
481+
*/
482+
public Builder setSSLTrustStorePassword(String password) {
483+
this.configuration.put(ClickHouseClientOption.KEY_STORE_PASSWORD.getKey(), password);
484+
return this;
485+
}
486+
487+
/**
488+
* Type of the SSL Trust Store. Usually JKS
489+
*
490+
* @param type
491+
* @return
492+
*/
493+
public Builder setSSLTrustStoreType(String type) {
494+
this.configuration.put(ClickHouseClientOption.KEY_STORE_TYPE.getKey(), type);
495+
return this;
496+
}
497+
498+
/**
499+
* Defines path to the key store file. It cannot be combined with
500+
* certificates. Either key store or certificates should be used.
501+
*
502+
* {@see setSSLKeyStorePassword} and {@see setSSLKeyStoreType}
503+
* @param path
504+
* @return
505+
*/
506+
public Builder setRootCertificate(String path) {
507+
this.configuration.put(ClickHouseClientOption.SSL_ROOT_CERTIFICATE.getKey(), path);
508+
return this;
509+
}
510+
511+
/**
512+
* Client certificate for mTLS.
513+
* @param path
514+
* @return
515+
*/
516+
public Builder setClientCertificate(String path) {
517+
this.configuration.put(ClickHouseClientOption.SSL_CERTIFICATE.getKey(), path);
518+
return this;
519+
}
520+
521+
/**
522+
* Client key for mTLS.
523+
* @param path
524+
* @return
525+
*/
526+
public Builder setClientKey(String path) {
527+
this.configuration.put(ClickHouseClientOption.SSL_KEY.getKey(), path);
528+
return this;
529+
}
530+
462531
public Client build() {
463532
// check if endpoint are empty. so can not initiate client
464533
if (this.endpoints.isEmpty()) {
@@ -469,6 +538,11 @@ public Client build() {
469538
throw new IllegalArgumentException("Username and password are required");
470539
}
471540

541+
if (this.configuration.containsKey(ClickHouseClientOption.TRUST_STORE) &&
542+
this.configuration.containsKey(ClickHouseClientOption.SSL_CERTIFICATE)) {
543+
throw new IllegalArgumentException("Trust store and certificates cannot be used together");
544+
}
545+
472546
this.configuration = setDefaults(this.configuration);
473547

474548
return new Client(this.endpoints, this.configuration, this.useNewImplementation);

0 commit comments

Comments
 (0)