From 0d4faece4577e167ae2ba20800712891efda45c9 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Tue, 29 Sep 2026 00:07:47 +0700 Subject: [PATCH 1/3] feat: support tls --- CHANGELOG.md | 4 + .../com/influxdb/internal/RestClientTest.java | 38 ++-- .../java/com/influxdb/utils/TlsUtils.java | 193 ++++++++++++++++++ .../client/InfluxDBClientOptions.java | 121 +++++++++++ .../client/InfluxDBClientOptionsTest.java | 85 +++++++- .../influxdb/client/InfluxDBClientTest.java | 153 ++++++++++++++ .../java/com/influxdb/client/tls/client.crt | 20 ++ .../java/com/influxdb/client/tls/client.key | 28 +++ .../java/com/influxdb/client/tls/client.p12 | Bin 0 -> 2682 bytes .../com/influxdb/client/tls/client_pkcs8.key | 30 +++ .../client/tls/generate-self-signed-cert.sh | 52 +++++ .../java/com/influxdb/client/tls/influxdb.crt | 21 ++ .../java/com/influxdb/client/tls/influxdb.key | 28 +++ .../java/com/influxdb/client/tls/influxdb.p12 | Bin 0 -> 2714 bytes .../com/influxdb/client/tls/other-server.crt | 21 ++ .../com/influxdb/client/tls/other-server.key | 28 +++ .../com/influxdb/client/tls/other-server.p12 | Bin 0 -> 2714 bytes pom.xml | 2 +- 18 files changed, 803 insertions(+), 21 deletions(-) create mode 100644 client-utils/src/main/java/com/influxdb/utils/TlsUtils.java create mode 100644 client/src/test/java/com/influxdb/client/tls/client.crt create mode 100644 client/src/test/java/com/influxdb/client/tls/client.key create mode 100644 client/src/test/java/com/influxdb/client/tls/client.p12 create mode 100644 client/src/test/java/com/influxdb/client/tls/client_pkcs8.key create mode 100644 client/src/test/java/com/influxdb/client/tls/generate-self-signed-cert.sh create mode 100644 client/src/test/java/com/influxdb/client/tls/influxdb.crt create mode 100644 client/src/test/java/com/influxdb/client/tls/influxdb.key create mode 100644 client/src/test/java/com/influxdb/client/tls/influxdb.p12 create mode 100644 client/src/test/java/com/influxdb/client/tls/other-server.crt create mode 100644 client/src/test/java/com/influxdb/client/tls/other-server.key create mode 100644 client/src/test/java/com/influxdb/client/tls/other-server.p12 diff --git a/CHANGELOG.md b/CHANGELOG.md index 186639517f1..b78334d5ecf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 8.1.0 [unreleased] +### Features + +- [#948](https://github.com/influxdata/influxdb-client-java/pull/948): Support TLS and mTls configurations. + ### Dependencies Update dependencies: diff --git a/client-core/src/test/java/com/influxdb/internal/RestClientTest.java b/client-core/src/test/java/com/influxdb/internal/RestClientTest.java index 0da95f5be9d..579d43cc6cd 100644 --- a/client-core/src/test/java/com/influxdb/internal/RestClientTest.java +++ b/client-core/src/test/java/com/influxdb/internal/RestClientTest.java @@ -26,6 +26,25 @@ import java.util.concurrent.CountDownLatch; import javax.annotation.Nonnull; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import okhttp3.logging.HttpLoggingInterceptor; +import okhttp3.mockwebserver.MockResponse; +import okio.Buffer; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import retrofit2.Call; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.http.GET; +import retrofit2.http.Headers; +import retrofit2.http.Path; + import com.influxdb.LogLevel; import com.influxdb.exceptions.BadGatewayException; import com.influxdb.exceptions.BadRequestException; @@ -46,25 +65,6 @@ import com.influxdb.exceptions.UnprocessableEntityException; import com.influxdb.test.AbstractMockServerTest; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Protocol; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.ResponseBody; -import okhttp3.logging.HttpLoggingInterceptor; -import okhttp3.mockwebserver.MockResponse; -import okio.Buffer; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import retrofit2.Call; -import retrofit2.Response; -import retrofit2.Retrofit; -import retrofit2.http.GET; -import retrofit2.http.Headers; -import retrofit2.http.Path; - /** * @author Jakub Bednar (bednar@github) (04/10/2018 07:57) */ diff --git a/client-utils/src/main/java/com/influxdb/utils/TlsUtils.java b/client-utils/src/main/java/com/influxdb/utils/TlsUtils.java new file mode 100644 index 00000000000..3d068ffc792 --- /dev/null +++ b/client-utils/src/main/java/com/influxdb/utils/TlsUtils.java @@ -0,0 +1,193 @@ +/* + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.influxdb.utils; + +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.GeneralSecurityException; +import java.security.KeyFactory; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Base64; +import java.util.Locale; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +public final class TlsUtils { + private static final String TLS = "TLS"; + private static final char[] DEFAULT_PASSWORD_CHAR_ARRAY = "".toCharArray(); + private static final String X509 = "X.509"; + private static final String PKCS12 = "PKCS12"; + + private TlsUtils() { + } + + @Nullable + public static SSLContext buildSslContext(@Nullable final KeyManagerFactory kmf, + @Nullable final TrustManagerFactory tmf) throws Exception { + if (kmf == null && tmf == null) { + return null; + } + + SSLContext sslContext = SSLContext.getInstance(TLS); + var trustManagers = tmf != null ? tmf.getTrustManagers() : null; + var keyManagers = kmf != null ? kmf.getKeyManagers() : null; + sslContext.init(keyManagers, trustManagers, null); + return sslContext; + } + + @Nonnull + public static X509TrustManager getX509TrustManager(@Nullable final TrustManagerFactory tmf) throws Exception { + TrustManagerFactory factory = tmf; + if (factory == null) { + factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + factory.init((KeyStore) null); + } + return (X509TrustManager) factory.getTrustManagers()[0]; + } + + public static X509Certificate loadCertificate(@Nonnull final String path) throws Exception { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return (X509Certificate) CertificateFactory.getInstance(X509) + .generateCertificate(new ByteArrayInputStream(encoded)); + } + + public static PrivateKey loadPrivateKey(@Nonnull final String path) throws Exception { + String keyPem = Files.readString(Paths.get(path)); + if (keyPem.contains("-----BEGIN ENCRYPTED PRIVATE KEY-----")) { + throw new IllegalArgumentException("Encrypted PKCS#8 private keys are not supported. Use an unencrypted " + + "PKCS#8 key or a PKCS#12 file."); + } + + if (!keyPem.contains("-----BEGIN PRIVATE KEY-----") + || !keyPem.contains("-----END PRIVATE KEY-----")) { + throw new IllegalArgumentException("Private key must be an unencrypted PKCS#8 PEM key."); + } + + String privateKeyPEM = keyPem + .replace("-----BEGIN PRIVATE KEY-----", "") + .replace("-----END PRIVATE KEY-----", "") + .replaceAll("\\s+", ""); + + byte[] encoded = Base64.getDecoder().decode(privateKeyPEM); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); + for (String algorithm : new String[]{"RSA", "EC", "DSA"}) { + try { + return KeyFactory.getInstance(algorithm).generatePrivate(keySpec); + } catch (java.security.spec.InvalidKeySpecException ignored) { + // Try the next supported algorithm. + } + } + + throw new GeneralSecurityException("Unsupported private key algorithm"); + } + + public static KeyManagerFactory createKmfP12(@Nonnull final String path, + @Nullable final char[] password) throws Exception { +// char[] pass = DEFAULT_PASSWORD_CHAR_ARRAY; +// if (password != null && password.length > 0) { +// pass = password; +// } + + char[] pass = password != null && password.length > 0 ? password : DEFAULT_PASSWORD_CHAR_ARRAY; + + KeyStore keyStore = KeyStore.getInstance(PKCS12); + try (FileInputStream fis = new FileInputStream(path)) { + keyStore.load(fis, pass); + } + + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(keyStore, pass); + return kmf; + } + + public static KeyManagerFactory createKmf(@Nonnull final String certPath, + @Nonnull final String keyPath) throws Exception { + X509Certificate certificate = TlsUtils.loadCertificate(certPath); + PrivateKey privateKey = TlsUtils.loadPrivateKey(keyPath); + + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null, null); + + keyStore.setKeyEntry("alias", privateKey, null, new Certificate[]{certificate}); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(keyStore, null); + + return kmf; + } + + // For .p12 only + public static TrustManagerFactory createTmfP12(@Nonnull final String path, + @Nullable final char[] password) throws Exception { +// char[] pass = "changeit".toCharArray(); +// if (password != null && password.length > 0) { +// pass = password; +// } + char[] pass = password != null && password.length > 0 ? password : DEFAULT_PASSWORD_CHAR_ARRAY; + + KeyStore trustStore = KeyStore.getInstance("PKCS12"); + try (FileInputStream fis = new FileInputStream(path)) { + trustStore.load(fis, pass); + } + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(trustStore); + + return tmf; + } + + public static TrustManagerFactory createTmf(@Nonnull final String path, + @Nullable final char[] password) throws Exception { + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + + String extension = path.toLowerCase(Locale.ROOT); + + if (extension.endsWith(".p12") || extension.endsWith(".pfx")) { + char[] pass = password != null && password.length > 0 ? password : DEFAULT_PASSWORD_CHAR_ARRAY; + tmf = createTmfP12(path, pass); + } else if (extension.endsWith(".crt") || extension.endsWith(".cert") || extension.endsWith(".pem")) { + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + try (FileInputStream fis = new FileInputStream(path)) { + X509Certificate cert = (X509Certificate) certFactory.generateCertificate(fis); + trustStore.setCertificateEntry("alias", cert); + } + tmf.init(trustStore); + } else { + throw new IllegalArgumentException("Unsupported certificate format"); + } + + return tmf; + } +} diff --git a/client/src/main/java/com/influxdb/client/InfluxDBClientOptions.java b/client/src/main/java/com/influxdb/client/InfluxDBClientOptions.java index 6ae4e0746a2..b8d8250ce9a 100644 --- a/client/src/main/java/com/influxdb/client/InfluxDBClientOptions.java +++ b/client/src/main/java/com/influxdb/client/InfluxDBClientOptions.java @@ -32,6 +32,10 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.NotThreadSafe; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; import com.influxdb.LogLevel; import com.influxdb.client.domain.WriteConsistency; @@ -40,6 +44,7 @@ import com.influxdb.client.write.WriteParameters; import com.influxdb.exceptions.InfluxException; import com.influxdb.utils.Arguments; +import com.influxdb.utils.TlsUtils; import okhttp3.HttpUrl; import okhttp3.OkHttpClient; @@ -65,6 +70,15 @@ public final class InfluxDBClientOptions { private final String username; private final char[] password; + private final String certificatePath; + private final String certificateKeyPath; + private final String certificateP12FilePath; + private final char[] keyPassword; + + private final String trustFilePath; + private final char[] trustFilePassword; + + private final String org; private final String bucket; private final WritePrecision precision; @@ -89,6 +103,13 @@ private InfluxDBClientOptions(@Nonnull final InfluxDBClientOptions.Builder build this.precision = builder.precision != null ? builder.precision : WriteParameters.DEFAULT_WRITE_PRECISION; this.consistency = builder.consistency; this.pointSettings = builder.pointSettings; + + this.certificatePath = builder.certificatePath; + this.certificateKeyPath = builder.certificateKeyPath; + this.certificateP12FilePath = builder.certificateP12FilePath; + this.keyPassword = builder.keyPassword; + this.trustFilePath = builder.trustFilePath; + this.trustFilePassword = builder.trustFilePassword; } /** @@ -238,6 +259,36 @@ public PointSettings getPointSettings() { return pointSettings; } + @Nullable + public String getCertificatePath() { + return certificatePath; + } + + @Nullable + public String getCertificateKeyPath() { + return certificateKeyPath; + } + + @Nullable + public String getCertificateP12FilePath() { + return certificateP12FilePath; + } + + @Nullable + public char[] getKeyPassword() { + return keyPassword; + } + + @Nullable + public String getTrustFilePath() { + return trustFilePath; + } + + @Nullable + public char[] getTrustFilePassword() { + return trustFilePassword; + } + /** * Creates a builder instance. * @@ -264,6 +315,14 @@ public static class Builder { private String username; private char[] password; + private String certificatePath; + private String certificateKeyPath; + private String certificateP12FilePath; + private char[] keyPassword; + + private String trustFilePath; + private char[] trustFilePassword; + private String org; private String bucket; private WritePrecision precision; @@ -448,6 +507,33 @@ public InfluxDBClientOptions.Builder consistency(@Nullable final WriteConsistenc return this; } + @Nonnull + public InfluxDBClientOptions.Builder certificateFilePath(@Nonnull final String certificatePath, + @Nonnull final String certificateKeyPath) { + this.certificatePath = certificatePath; + this.certificateKeyPath = certificateKeyPath; + + return this; + } + + @Nonnull + public InfluxDBClientOptions.Builder certificateP12FilePath(@Nonnull final String p12FilePath, + @Nullable final char[] password) { + this.certificateP12FilePath = p12FilePath; + this.keyPassword = password; + + return this; + } + + @Nonnull + public InfluxDBClientOptions.Builder trustFilePath(@Nonnull final String trustFilePath, + @Nullable final char[] password) { + this.trustFilePath = trustFilePath; + this.trustFilePassword = password; + + return this; + } + /** * Add default tag that will be use for writes by Point and POJO. *

@@ -584,6 +670,8 @@ public InfluxDBClientOptions build() { .protocols(Collections.singletonList(Protocol.HTTP_1_1)); } + configureTls(okHttpClient); + if (logLevel == null) { logLevel = LogLevel.NONE; } @@ -591,6 +679,39 @@ public InfluxDBClientOptions build() { return new InfluxDBClientOptions(this); } + private void configureTls(@Nonnull final OkHttpClient.Builder okHttpClient) { + + if (certificatePath != null && certificateP12FilePath != null) { + throw new IllegalArgumentException("Cannot set both p12FilePath and certificatePath"); + } + + if (certificatePath == null && certificateP12FilePath == null && trustFilePath == null) { + return; + } + + try { + TrustManagerFactory tmf = null; + if (trustFilePath != null) { + tmf = TlsUtils.createTmf(trustFilePath, trustFilePassword); + } + + KeyManagerFactory kmf = null; + if (certificatePath != null) { + kmf = TlsUtils.createKmf(certificatePath, certificateKeyPath); + } else if (certificateP12FilePath != null) { + kmf = TlsUtils.createKmfP12(certificateP12FilePath, keyPassword); + } + + SSLContext sslContext = TlsUtils.buildSslContext(kmf, tmf); + if (sslContext != null) { + X509TrustManager trustManager = TlsUtils.getX509TrustManager(tmf); + okHttpClient.sslSocketFactory(sslContext.getSocketFactory(), trustManager); + } + } catch (Exception e) { + throw new InfluxException(e); + } + } + @Nonnull private InfluxDBClientOptions.Builder configure(@Nonnull final String url, @Nullable final String org, diff --git a/client/src/test/java/com/influxdb/client/InfluxDBClientOptionsTest.java b/client/src/test/java/com/influxdb/client/InfluxDBClientOptionsTest.java index c95ae134bd6..723e69b40f1 100644 --- a/client/src/test/java/com/influxdb/client/InfluxDBClientOptionsTest.java +++ b/client/src/test/java/com/influxdb/client/InfluxDBClientOptionsTest.java @@ -27,8 +27,9 @@ import java.util.Map; import com.influxdb.client.domain.WritePrecision; - import com.influxdb.exceptions.InfluxException; +import com.influxdb.utils.TlsUtils; + import okhttp3.OkHttpClient; import okhttp3.Protocol; import org.assertj.core.api.Assertions; @@ -153,6 +154,37 @@ public void customClientTypeFromConnectionString() { Assertions.assertThat(options.getClientType()).isEqualTo("url-service"); } + @Test + public void tlsFilesConfig() { + String tlsDir = "src/test/java/com/influxdb/client/tls/"; + String influxdbCertPath = tlsDir + "influxdb.crt"; + String clientCertPath = tlsDir + "client.crt"; + String clientKeyPath = tlsDir + "client.key"; + String clientP12 = tlsDir + "client.p12"; + + + InfluxDBClientOptions options = InfluxDBClientOptions.builder() + .url("http://localhost:8086") + .trustFilePath(influxdbCertPath, null) + .certificateFilePath(clientCertPath, clientKeyPath) + .build(); + + Assertions.assertThat(options.getTrustFilePath()).isEqualTo(influxdbCertPath); + Assertions.assertThat(options.getTrustFilePassword()).isEqualTo(null); + Assertions.assertThat(options.getCertificatePath()).isEqualTo(clientCertPath); + Assertions.assertThat(options.getCertificateKeyPath()).isEqualTo(clientKeyPath); + Assertions.assertThat(options.getKeyPassword()).isEqualTo(null); + + // For .p12 files + InfluxDBClientOptions options1 = InfluxDBClientOptions.builder() + .url("http://localhost:8086") + .certificateP12FilePath(clientP12, null) + .build(); + + Assertions.assertThat(options1.getCertificateP12FilePath()).isEqualTo(clientP12); + Assertions.assertThat(options1.getKeyPassword()).isEqualTo(null); + } + @Test public void customClientTypeFromProperties() { InfluxDBClientOptions options = InfluxDBClientOptions.builder().loadProperties().build(); @@ -223,7 +255,58 @@ public void ipv6Invalid(){ .build();}).isInstanceOf(InfluxException.class) .hasMessage(String.format("Unable to parse connection string http://%s:9999/api/v2/query?orgID=my-org", ipv6)); } + } + + @Test + void tlsBothCertificateAndP12Configured() { + Assertions.assertThatThrownBy(() -> InfluxDBClientOptions.builder() + .url("https://localhost:9999") + .certificateFilePath("cert.pem", "key.pem") + .certificateP12FilePath("client.p12", null) + .build()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Cannot set both p12FilePath and certificatePath"); + } + @Test + void tlsOnlyClientCertificatesConfigured() { + String clientCertPath = "src/test/java/com/influxdb/client/tls/client.crt"; + String clientKeyPath = "src/test/java/com/influxdb/client/tls/client.key"; + + InfluxDBClientOptions options = InfluxDBClientOptions.builder() + .url("https://localhost:9999") + .certificateFilePath(clientCertPath, clientKeyPath) + .build(); + + Assertions.assertThat(options.getOkHttpClient()).isNotNull(); } + @Test + void tlsOnlyClientP12Configured() { + String clientP12 = "src/test/java/com/influxdb/client/tls/client.p12"; + + InfluxDBClientOptions options = InfluxDBClientOptions.builder() + .url("https://localhost:9999") + .certificateP12FilePath(clientP12, null) + .build(); + + Assertions.assertThat(options.getOkHttpClient()).isNotNull(); + } + + @Test + void tlsInvalidCertificatePath() { + Assertions.assertThatThrownBy(() -> InfluxDBClientOptions.builder() + .url("https://localhost:9999") + .certificateFilePath("non_existing_file.pem", "non_existing_file.key") + .build()) + .isInstanceOf(InfluxException.class); + } + + @Test + void encryptedPemKeyIsRejected() { + Assertions.assertThatThrownBy(() -> + TlsUtils.loadPrivateKey("src/test/java/com/influxdb/client/tls/client_pkcs8.key")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Encrypted PKCS#8 private keys are not supported"); + } } \ No newline at end of file diff --git a/client/src/test/java/com/influxdb/client/InfluxDBClientTest.java b/client/src/test/java/com/influxdb/client/InfluxDBClientTest.java index d706e4d9e3b..e840c9ff0aa 100644 --- a/client/src/test/java/com/influxdb/client/InfluxDBClientTest.java +++ b/client/src/test/java/com/influxdb/client/InfluxDBClientTest.java @@ -30,6 +30,10 @@ import java.util.logging.LogRecord; import java.util.logging.Logger; import javax.annotation.Nonnull; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; import okhttp3.HttpUrl; import okhttp3.Interceptor; @@ -53,6 +57,7 @@ import com.influxdb.client.domain.WritePrecision; import com.influxdb.client.internal.AbstractInfluxDBClientTest; import com.influxdb.client.service.InfluxQLQueryService; +import com.influxdb.utils.TlsUtils; /** * @author Jakub Bednar (bednar@github) (05/09/2018 14:00) @@ -421,6 +426,128 @@ public Response intercept(@Nonnull final Chain chain) throws IOException { proxy.shutdown(); } + String tlsDir = "src/test/java/com/influxdb/client/tls/"; + + String influxdbCertPath = tlsDir + "influxdb.crt"; + String influxdbKeyPath = tlsDir + "influxdb.key"; + String influxdbP12 = tlsDir + "influxdb.p12"; + + String otherCertPath = tlsDir + "other-server.crt"; + String otherKeyCertPath = tlsDir + "other-server.key"; + String otherP12 = tlsDir + "other-server.p12"; + + String clientCertPath = tlsDir + "client.crt"; + String clientKeyPath = tlsDir + "client.key"; + String clientP12 = tlsDir + "client.p12"; + + record TlsTest(boolean isMutualTls, boolean isP12) { + } + + private static List tlsCases() { + return List.of( + new TlsTest(false, false), + new TlsTest(false, true), + new TlsTest(true, false), + new TlsTest(true, true) + ); + } + + @Test + public void testMutualTlsSuccess() throws Exception { + for (TlsTest tlsCase : tlsCases()) { + boolean isMutualTls = tlsCase.isMutualTls; + boolean isP12 = tlsCase.isP12; + + MockWebServer mockServer = getMutualTlsMockServer(isMutualTls, isP12); + try { + InfluxDBClientOptions.Builder options = InfluxDBClientOptions.builder() + .url(mockServer.url("/").url().toString()) + .authenticateToken("my-token".toCharArray()) + .trustFilePath(isP12 ? influxdbP12 : influxdbCertPath, null); + + if (isMutualTls) { + if (isP12) { + options.certificateP12FilePath(clientP12, null); + } else { + options.certificateFilePath(clientCertPath, clientKeyPath); + } + } + + try (InfluxDBClient client = InfluxDBClientFactory.create(options.build())) { + client.version(); + } + } finally { + mockServer.shutdown(); + } + } + } + + @Test + public void testMutualTlsFailClientUntrustedServer() throws Exception { + // Client trusts other cert, but server uses influxdb cert -> handshake should fail + for (boolean isP12 : List.of(false, true)) { + MockWebServer mockServer = getMutualTlsMockServer(false, isP12); + InfluxDBClientOptions.Builder options = InfluxDBClientOptions.builder() + .url(mockServer.url("/").url().toString()) + .authenticateToken("my-token".toCharArray()); + if (isP12) { + options.trustFilePath(otherP12, null); + } else { + options.trustFilePath(otherCertPath, null); + } + + try (InfluxDBClient client = InfluxDBClientFactory.create(options.build())) { + Assertions.assertThatThrownBy(client::version) + .isInstanceOf(com.influxdb.exceptions.InfluxException.class); + } finally { + mockServer.shutdown(); + } + } + } + + @Test + public void testMutualTlsFailServerUntrustedClient() throws Exception { + // Server requires client auth and trusts client cert, but client provides wrong (other) cert -> handshake should fail + for (boolean isP12 : List.of(false, true)) { + MockWebServer mockServer = getMutualTlsMockServer(true, isP12); + InfluxDBClientOptions.Builder options = InfluxDBClientOptions.builder() + .url(mockServer.url("/").url().toString()) + .authenticateToken("my-token".toCharArray()); + + if (isP12) { + options.certificateP12FilePath(otherP12, null) + .trustFilePath(influxdbP12, null); + } else { + options.certificateFilePath(otherCertPath, otherKeyCertPath) + .trustFilePath(influxdbCertPath, null); + } + + try (InfluxDBClient client = InfluxDBClientFactory.create(options.build())) { + Assertions.assertThatThrownBy(client::version) + .isInstanceOf(com.influxdb.exceptions.InfluxException.class); + } finally { + mockServer.shutdown(); + } + } + } + + @Test + public void testMutualTlsSuccessDifferentFileTypes() throws Exception { + MockWebServer mockServer = getMutualTlsMockServer(true, true); + InfluxDBClientOptions options = InfluxDBClientOptions.builder() + .url(mockServer.url("/").url().toString()) + .certificateFilePath(clientCertPath, clientKeyPath) + .trustFilePath(influxdbP12, null) + .authenticateToken("my-token".toCharArray()) + .build(); + + try (InfluxDBClient client = InfluxDBClientFactory.create(options)) { + client.version(); + } finally { + mockServer.shutdown(); + } + } + @Test public void connectionStringPrecision() { InfluxDBClientOptions options = InfluxDBClientOptions.builder() @@ -547,4 +674,30 @@ private void queryAndTest(final String expected) throws InterruptedException { Assertions.assertThat(request.getRequestUrl()).isNotNull(); Assertions.assertThat(request.getRequestUrl().toString()).isEqualTo(expected + "?org=my-org"); } + + private MockWebServer getMutualTlsMockServer(boolean isMutualTls, boolean isP12) throws Exception { + KeyManagerFactory kmf; + TrustManagerFactory tmf; + + if (isP12) { + kmf = TlsUtils.createKmfP12(influxdbP12, null); + tmf = isMutualTls ? TlsUtils.createTmfP12(clientP12, null) : null; + } else { + kmf = TlsUtils.createKmf(influxdbCertPath, influxdbKeyPath); + tmf = isMutualTls ? TlsUtils.createTmf(clientCertPath, null) : null; + } + + SSLContext sslContext = TlsUtils.buildSslContext(kmf, tmf); + + var mockServer = new MockWebServer(); + mockServer.useHttps(sslContext.getSocketFactory(), false); + + if (isMutualTls) { + mockServer.requireClientAuth(); + } + mockServer.start(); + mockServer.enqueue(createResponse("ok")); + + return mockServer; + } } \ No newline at end of file diff --git a/client/src/test/java/com/influxdb/client/tls/client.crt b/client/src/test/java/com/influxdb/client/tls/client.crt new file mode 100644 index 00000000000..5da7d9bc42b --- /dev/null +++ b/client/src/test/java/com/influxdb/client/tls/client.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIUINAESINikGsy0TadFTufAgb1xfgwDQYJKoZIhvcNAQEL +BQAwOTEUMBIGA1UEAwwLdGVzdC1jbGllbnQxFDASBgNVBAoMC0RldmVsb3BtZW50 +MQswCQYDVQQGEwJVUzAeFw0yNjA5MjkxMDAxMDdaFw0zNjA5MjYxMDAxMDdaMDkx +FDASBgNVBAMMC3Rlc3QtY2xpZW50MRQwEgYDVQQKDAtEZXZlbG9wbWVudDELMAkG +A1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCSAjlTbSl6 +xgYgOD4i4Kf0sM9rMbPnta1l3ADfeQYVNUFg8wOn/FPn6lpcn6SY6uaivde+vgrk +xpwTVSTYATzhM9uej2UEoOf3MsV7WsIAipVMWHkcbYU5zNmS5Re8NjjFpe1ivD0f +Kaap4Fs1cva5uTWAv8QVQHorZiHMiSYVlwKedgHVuD8m63Yzgey9QK/k97v5pdO6 +/kQcyZZmA7k0KaEoDu825kuXsS4gOu6LwYm5MMWKyVI2BVsVS9RsnsyspDQoHkOd +ynwZnrWEdEznZ8BbFXpxfNo0V/epIpvyu6fj3LYF7xiK1wDcpzuYAFwLyHQsKyx/ +XTjAFZScisGlAgMBAAGjUzBRMB0GA1UdDgQWBBTFfSyVN+h0LsXm9KwGxZzUA6Bd +2jAfBgNVHSMEGDAWgBTFfSyVN+h0LsXm9KwGxZzUA6Bd2jAPBgNVHRMBAf8EBTAD +AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAOqEqtloio/Bu3FTQLug0uOsPbitpyZt4Y +4+9XervfTVzBfx5NSU8kFf+tdoJdkqiO7tl6z51jo2E4nG0XzaBy1vLGuCFy2eos +CLW/tQtO4pZPLHIVOmhjk19W8Q0Szm51rqfxFc9kONaGrtTS5qdsh3b7v/zul9nV +UG0fGu3RRxM1brfDzzpDMBFgv+vQOiziB05E3c2UxQaAWPEA+e2wz5hBG95A07X6 +K4ZYfXaH594bplnWazuDWTqjK433+U/+V4geDVwP9gWX8yXSk39BWIPvAwub8WoF +HwMWuk7+rb2r+wD/fl6hsy51ob+ayT6D1kbnFRq+Jve1ss7yx+pg +-----END CERTIFICATE----- diff --git a/client/src/test/java/com/influxdb/client/tls/client.key b/client/src/test/java/com/influxdb/client/tls/client.key new file mode 100644 index 00000000000..5e63c80deac --- /dev/null +++ b/client/src/test/java/com/influxdb/client/tls/client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCSAjlTbSl6xgYg +OD4i4Kf0sM9rMbPnta1l3ADfeQYVNUFg8wOn/FPn6lpcn6SY6uaivde+vgrkxpwT +VSTYATzhM9uej2UEoOf3MsV7WsIAipVMWHkcbYU5zNmS5Re8NjjFpe1ivD0fKaap +4Fs1cva5uTWAv8QVQHorZiHMiSYVlwKedgHVuD8m63Yzgey9QK/k97v5pdO6/kQc +yZZmA7k0KaEoDu825kuXsS4gOu6LwYm5MMWKyVI2BVsVS9RsnsyspDQoHkOdynwZ +nrWEdEznZ8BbFXpxfNo0V/epIpvyu6fj3LYF7xiK1wDcpzuYAFwLyHQsKyx/XTjA +FZScisGlAgMBAAECggEAMS40lwhPD37CM3oeW+smR8KCq027lpHYjVXUqXF/fgdJ +NVnF4oCY1qZWt5pCfAurkie2Exa6XqMTkWN9nJCWLBkmobsVQMDeQaLFaC6C6GHF +tkiaytuNI5H/u34VR51P9CtW0YosYGHMNK5QqqlFt/tNrUdqyenE/PdS7S1JOb34 +dsmXteNqsUK2iRVBYxyRT2XAOCxFABgn7KkjzR28F7/mK7HKrF3momkFP6d6nnGv +kEc3Ngc3IT5T/pNfObrgrO1uUpzira6x8p2Zx4eenalwaMV239VHAtqBu2DvHDpQ +MXW4gCEfDtRAUx1O8U9VaTmYhyq9ewzRvKD7RWqK5QKBgQDNOkV6uXha2M2Q252c +FfYoD34FL22aKDipvboZ1Qlv6Vmul34hKdNGqoagT1+ZxeRUhWGk/J1JUeG8eDRg +ocJRKsoYSphDA+RxXk7GICx1lYmjtE6Ao7D2oLDkUA0N2lXyvjkpNvMB+t+VUY/u +xtHMJjv8B7O9DBThzX4mdmOFNwKBgQC2IW0LvNpDFvsSrX2Py0DgjM8bHW7MLRy9 +yki2KjBTOaA6POIkCiseEJNJ9HlJ045xK4UZU+Sbp8K/noxujKqQo5APaOo4ARU1 +5DgxHAQjGhAjyu0QWzTXkpFw0duB29hoLncNr5LDeL789pwGbcVKEND/cgXlF0sF +Xs4HgDpeAwKBgGyAp2U4E7qsLxqsEcsJDWimsDDbn23GYBbV+UNZD7E8RS76ZzPv +YgVVePHepSOurYZGMpbA/ANcqCU1xDNmsk6pecmX/qJHt4p8mtdDAV51XhzP4kU+ +xfvOf1dmP1CYo6JAEgaJR7c/ROA0DA3ozdjKSiJ4i/2iGpQ7SbvaEcnHAoGBAKZc +BdTQ3bSmSxOWcLhleY8iTxJ/YfMRycz59kyeYKHEYzyO3Cj7OMMvdLn6msb6fIOW +su6dmJUtOU/6LF/WEP4oyK+qrzYUlyEworsI0iaV6eQnuT5VcQDvmfWpWo1VGGig ++JIBq1bs9dbuEzo0Dh9HGQAbUJMfIaF4JUzorWetAoGBAJ4MwpSKCLAxngZWV0C+ +qLYZEtKgIRhs4LPII8lkLZJnb7O3V4tTFHhtyZKpI9bdHi+lH7UV5z3m/hLvYh64 +Ltzb4loGxtCpyPc0295ttV5l2b1zY2F2gO8ddCF8w6G8Oq4uRaN1F2rg1TLKiLgS +E8HtcLGUkdtrx4m1aQuKC3j5 +-----END PRIVATE KEY----- diff --git a/client/src/test/java/com/influxdb/client/tls/client.p12 b/client/src/test/java/com/influxdb/client/tls/client.p12 new file mode 100644 index 0000000000000000000000000000000000000000..3472fb0687dbc4c581edf31c9f064d5b44d36b27 GIT binary patch literal 2682 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 literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml index c270dab71b6..9aad10b608c 100644 --- a/pom.xml +++ b/pom.xml @@ -242,7 +242,7 @@ **/*nightly*/**, **/.m2/**, LICENSE, **/*.md, **/PLACEHOLDER, **/.influxdb/**, **/generated/**, **/openapi-generator/**, **/swagger.yml, **/*.json, **/spring.factories, **/PULL_REQUEST_TEMPLATE, release.properties/, **/pom.xml.releaseBackup, **/pom.xml.tag, **/semantic.yml, **/test.txt, **/*.csv, - codecov.yml, **/flowable/*.java, **/spring/*.imports + codecov.yml, **/flowable/*.java, **/spring/*.imports, **/*.p12, **/*.crt, **/*.key ${project.organization.name} From 8390a8dd58a020c7ee17c4a84181bd4cf5b76bd6 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Tue, 29 Sep 2026 17:34:45 +0700 Subject: [PATCH 2/3] feat: support tls --- .../java/com/influxdb/utils/TlsUtils.java | 15 ----- .../client/InfluxDBClientOptionsTest.java | 10 ++-- .../influxdb/client/InfluxDBClientTest.java | 27 +++++---- .../java/com/influxdb/client/tls/client.crt | 32 +++++----- .../java/com/influxdb/client/tls/client.key | 52 ++++++++-------- .../java/com/influxdb/client/tls/client.p12 | Bin 2682 -> 2682 bytes .../com/influxdb/client/tls/client_pkcs8.key | 56 +++++++++--------- .../client/tls/generate-self-signed-cert.sh | 2 +- .../java/com/influxdb/client/tls/influxdb.crt | 34 +++++------ .../java/com/influxdb/client/tls/influxdb.key | 52 ++++++++-------- .../java/com/influxdb/client/tls/influxdb.p12 | Bin 2714 -> 2714 bytes .../com/influxdb/client/tls/other-server.crt | 32 +++++----- .../com/influxdb/client/tls/other-server.key | 52 ++++++++-------- .../com/influxdb/client/tls/other-server.p12 | Bin 2714 -> 2714 bytes 14 files changed, 176 insertions(+), 188 deletions(-) diff --git a/client-utils/src/main/java/com/influxdb/utils/TlsUtils.java b/client-utils/src/main/java/com/influxdb/utils/TlsUtils.java index 3d068ffc792..b6afaf47bea 100644 --- a/client-utils/src/main/java/com/influxdb/utils/TlsUtils.java +++ b/client-utils/src/main/java/com/influxdb/utils/TlsUtils.java @@ -88,11 +88,6 @@ public static PrivateKey loadPrivateKey(@Nonnull final String path) throws Excep + "PKCS#8 key or a PKCS#12 file."); } - if (!keyPem.contains("-----BEGIN PRIVATE KEY-----") - || !keyPem.contains("-----END PRIVATE KEY-----")) { - throw new IllegalArgumentException("Private key must be an unencrypted PKCS#8 PEM key."); - } - String privateKeyPEM = keyPem .replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") @@ -104,7 +99,6 @@ public static PrivateKey loadPrivateKey(@Nonnull final String path) throws Excep try { return KeyFactory.getInstance(algorithm).generatePrivate(keySpec); } catch (java.security.spec.InvalidKeySpecException ignored) { - // Try the next supported algorithm. } } @@ -113,11 +107,6 @@ public static PrivateKey loadPrivateKey(@Nonnull final String path) throws Excep public static KeyManagerFactory createKmfP12(@Nonnull final String path, @Nullable final char[] password) throws Exception { -// char[] pass = DEFAULT_PASSWORD_CHAR_ARRAY; -// if (password != null && password.length > 0) { -// pass = password; -// } - char[] pass = password != null && password.length > 0 ? password : DEFAULT_PASSWORD_CHAR_ARRAY; KeyStore keyStore = KeyStore.getInstance(PKCS12); @@ -149,10 +138,6 @@ public static KeyManagerFactory createKmf(@Nonnull final String certPath, // For .p12 only public static TrustManagerFactory createTmfP12(@Nonnull final String path, @Nullable final char[] password) throws Exception { -// char[] pass = "changeit".toCharArray(); -// if (password != null && password.length > 0) { -// pass = password; -// } char[] pass = password != null && password.length > 0 ? password : DEFAULT_PASSWORD_CHAR_ARRAY; KeyStore trustStore = KeyStore.getInstance("PKCS12"); diff --git a/client/src/test/java/com/influxdb/client/InfluxDBClientOptionsTest.java b/client/src/test/java/com/influxdb/client/InfluxDBClientOptionsTest.java index 723e69b40f1..6a6cf6295ab 100644 --- a/client/src/test/java/com/influxdb/client/InfluxDBClientOptionsTest.java +++ b/client/src/test/java/com/influxdb/client/InfluxDBClientOptionsTest.java @@ -162,7 +162,6 @@ public void tlsFilesConfig() { String clientKeyPath = tlsDir + "client.key"; String clientP12 = tlsDir + "client.p12"; - InfluxDBClientOptions options = InfluxDBClientOptions.builder() .url("http://localhost:8086") .trustFilePath(influxdbCertPath, null) @@ -170,19 +169,18 @@ public void tlsFilesConfig() { .build(); Assertions.assertThat(options.getTrustFilePath()).isEqualTo(influxdbCertPath); - Assertions.assertThat(options.getTrustFilePassword()).isEqualTo(null); Assertions.assertThat(options.getCertificatePath()).isEqualTo(clientCertPath); Assertions.assertThat(options.getCertificateKeyPath()).isEqualTo(clientKeyPath); - Assertions.assertThat(options.getKeyPassword()).isEqualTo(null); // For .p12 files + var password = "changeit".toCharArray(); InfluxDBClientOptions options1 = InfluxDBClientOptions.builder() .url("http://localhost:8086") - .certificateP12FilePath(clientP12, null) + .certificateP12FilePath(clientP12, password) .build(); Assertions.assertThat(options1.getCertificateP12FilePath()).isEqualTo(clientP12); - Assertions.assertThat(options1.getKeyPassword()).isEqualTo(null); + Assertions.assertThat(options1.getKeyPassword()).isEqualTo(password); } @Test @@ -287,7 +285,7 @@ void tlsOnlyClientP12Configured() { InfluxDBClientOptions options = InfluxDBClientOptions.builder() .url("https://localhost:9999") - .certificateP12FilePath(clientP12, null) + .certificateP12FilePath(clientP12, "changeit".toCharArray()) .build(); Assertions.assertThat(options.getOkHttpClient()).isNotNull(); diff --git a/client/src/test/java/com/influxdb/client/InfluxDBClientTest.java b/client/src/test/java/com/influxdb/client/InfluxDBClientTest.java index e840c9ff0aa..d160343efec 100644 --- a/client/src/test/java/com/influxdb/client/InfluxDBClientTest.java +++ b/client/src/test/java/com/influxdb/client/InfluxDBClientTest.java @@ -457,17 +457,18 @@ public void testMutualTlsSuccess() throws Exception { for (TlsTest tlsCase : tlsCases()) { boolean isMutualTls = tlsCase.isMutualTls; boolean isP12 = tlsCase.isP12; + char[] password = "changeit".toCharArray(); MockWebServer mockServer = getMutualTlsMockServer(isMutualTls, isP12); try { InfluxDBClientOptions.Builder options = InfluxDBClientOptions.builder() .url(mockServer.url("/").url().toString()) .authenticateToken("my-token".toCharArray()) - .trustFilePath(isP12 ? influxdbP12 : influxdbCertPath, null); + .trustFilePath(isP12 ? influxdbP12 : influxdbCertPath, password); if (isMutualTls) { if (isP12) { - options.certificateP12FilePath(clientP12, null); + options.certificateP12FilePath(clientP12, password); } else { options.certificateFilePath(clientCertPath, clientKeyPath); } @@ -486,14 +487,15 @@ public void testMutualTlsSuccess() throws Exception { public void testMutualTlsFailClientUntrustedServer() throws Exception { // Client trusts other cert, but server uses influxdb cert -> handshake should fail for (boolean isP12 : List.of(false, true)) { + char[] password = "changeit".toCharArray(); MockWebServer mockServer = getMutualTlsMockServer(false, isP12); InfluxDBClientOptions.Builder options = InfluxDBClientOptions.builder() .url(mockServer.url("/").url().toString()) .authenticateToken("my-token".toCharArray()); if (isP12) { - options.trustFilePath(otherP12, null); + options.trustFilePath(otherP12, password); } else { - options.trustFilePath(otherCertPath, null); + options.trustFilePath(otherCertPath, password); } try (InfluxDBClient client = InfluxDBClientFactory.create(options.build())) { @@ -509,17 +511,18 @@ public void testMutualTlsFailClientUntrustedServer() throws Exception { public void testMutualTlsFailServerUntrustedClient() throws Exception { // Server requires client auth and trusts client cert, but client provides wrong (other) cert -> handshake should fail for (boolean isP12 : List.of(false, true)) { + char[] password = "changeit".toCharArray(); MockWebServer mockServer = getMutualTlsMockServer(true, isP12); InfluxDBClientOptions.Builder options = InfluxDBClientOptions.builder() .url(mockServer.url("/").url().toString()) .authenticateToken("my-token".toCharArray()); if (isP12) { - options.certificateP12FilePath(otherP12, null) - .trustFilePath(influxdbP12, null); + options.certificateP12FilePath(otherP12, password) + .trustFilePath(influxdbP12, password); } else { options.certificateFilePath(otherCertPath, otherKeyCertPath) - .trustFilePath(influxdbCertPath, null); + .trustFilePath(influxdbCertPath, password); } try (InfluxDBClient client = InfluxDBClientFactory.create(options.build())) { @@ -537,7 +540,7 @@ public void testMutualTlsSuccessDifferentFileTypes() throws Exception { InfluxDBClientOptions options = InfluxDBClientOptions.builder() .url(mockServer.url("/").url().toString()) .certificateFilePath(clientCertPath, clientKeyPath) - .trustFilePath(influxdbP12, null) + .trustFilePath(influxdbP12, "changeit".toCharArray()) .authenticateToken("my-token".toCharArray()) .build(); @@ -679,12 +682,14 @@ private MockWebServer getMutualTlsMockServer(boolean isMutualTls, boolean isP12) KeyManagerFactory kmf; TrustManagerFactory tmf; + char[] password = "changeit".toCharArray(); + if (isP12) { - kmf = TlsUtils.createKmfP12(influxdbP12, null); - tmf = isMutualTls ? TlsUtils.createTmfP12(clientP12, null) : null; + kmf = TlsUtils.createKmfP12(influxdbP12, password); + tmf = isMutualTls ? TlsUtils.createTmfP12(clientP12, password) : null; } else { kmf = TlsUtils.createKmf(influxdbCertPath, influxdbKeyPath); - tmf = isMutualTls ? TlsUtils.createTmf(clientCertPath, null) : null; + tmf = isMutualTls ? TlsUtils.createTmf(clientCertPath, password) : null; } SSLContext sslContext = TlsUtils.buildSslContext(kmf, tmf); diff --git a/client/src/test/java/com/influxdb/client/tls/client.crt b/client/src/test/java/com/influxdb/client/tls/client.crt index 5da7d9bc42b..b9c82617ca0 100644 --- a/client/src/test/java/com/influxdb/client/tls/client.crt +++ b/client/src/test/java/com/influxdb/client/tls/client.crt @@ -1,20 +1,20 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/client/src/test/java/com/influxdb/client/tls/client.key b/client/src/test/java/com/influxdb/client/tls/client.key index 5e63c80deac..091953b0684 100644 --- a/client/src/test/java/com/influxdb/client/tls/client.key +++ b/client/src/test/java/com/influxdb/client/tls/client.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCSAjlTbSl6xgYg -OD4i4Kf0sM9rMbPnta1l3ADfeQYVNUFg8wOn/FPn6lpcn6SY6uaivde+vgrkxpwT -VSTYATzhM9uej2UEoOf3MsV7WsIAipVMWHkcbYU5zNmS5Re8NjjFpe1ivD0fKaap -4Fs1cva5uTWAv8QVQHorZiHMiSYVlwKedgHVuD8m63Yzgey9QK/k97v5pdO6/kQc -yZZmA7k0KaEoDu825kuXsS4gOu6LwYm5MMWKyVI2BVsVS9RsnsyspDQoHkOdynwZ -nrWEdEznZ8BbFXpxfNo0V/epIpvyu6fj3LYF7xiK1wDcpzuYAFwLyHQsKyx/XTjA -FZScisGlAgMBAAECggEAMS40lwhPD37CM3oeW+smR8KCq027lpHYjVXUqXF/fgdJ -NVnF4oCY1qZWt5pCfAurkie2Exa6XqMTkWN9nJCWLBkmobsVQMDeQaLFaC6C6GHF -tkiaytuNI5H/u34VR51P9CtW0YosYGHMNK5QqqlFt/tNrUdqyenE/PdS7S1JOb34 -dsmXteNqsUK2iRVBYxyRT2XAOCxFABgn7KkjzR28F7/mK7HKrF3momkFP6d6nnGv -kEc3Ngc3IT5T/pNfObrgrO1uUpzira6x8p2Zx4eenalwaMV239VHAtqBu2DvHDpQ -MXW4gCEfDtRAUx1O8U9VaTmYhyq9ewzRvKD7RWqK5QKBgQDNOkV6uXha2M2Q252c -FfYoD34FL22aKDipvboZ1Qlv6Vmul34hKdNGqoagT1+ZxeRUhWGk/J1JUeG8eDRg -ocJRKsoYSphDA+RxXk7GICx1lYmjtE6Ao7D2oLDkUA0N2lXyvjkpNvMB+t+VUY/u -xtHMJjv8B7O9DBThzX4mdmOFNwKBgQC2IW0LvNpDFvsSrX2Py0DgjM8bHW7MLRy9 -yki2KjBTOaA6POIkCiseEJNJ9HlJ045xK4UZU+Sbp8K/noxujKqQo5APaOo4ARU1 -5DgxHAQjGhAjyu0QWzTXkpFw0duB29hoLncNr5LDeL789pwGbcVKEND/cgXlF0sF -Xs4HgDpeAwKBgGyAp2U4E7qsLxqsEcsJDWimsDDbn23GYBbV+UNZD7E8RS76ZzPv -YgVVePHepSOurYZGMpbA/ANcqCU1xDNmsk6pecmX/qJHt4p8mtdDAV51XhzP4kU+ -xfvOf1dmP1CYo6JAEgaJR7c/ROA0DA3ozdjKSiJ4i/2iGpQ7SbvaEcnHAoGBAKZc -BdTQ3bSmSxOWcLhleY8iTxJ/YfMRycz59kyeYKHEYzyO3Cj7OMMvdLn6msb6fIOW -su6dmJUtOU/6LF/WEP4oyK+qrzYUlyEworsI0iaV6eQnuT5VcQDvmfWpWo1VGGig -+JIBq1bs9dbuEzo0Dh9HGQAbUJMfIaF4JUzorWetAoGBAJ4MwpSKCLAxngZWV0C+ -qLYZEtKgIRhs4LPII8lkLZJnb7O3V4tTFHhtyZKpI9bdHi+lH7UV5z3m/hLvYh64 -Ltzb4loGxtCpyPc0295ttV5l2b1zY2F2gO8ddCF8w6G8Oq4uRaN1F2rg1TLKiLgS -E8HtcLGUkdtrx4m1aQuKC3j5 +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC+27lZ3TDTEK8r +vgmFA4VM+632NaDzzRPs+hNO62vLbjgirimRY1NImnR/Nd5Bjxz04nwKvnyggegO +xdxeGY+1U+ErMexP7LZ5rpJyI6XF9AjLPN1G96seYq5/B5QghR7Lm4O6VeagP3EJ +J8m1Ul4PGjvPD+fPMXV0PEo38kSS0//DCFVy5vkvhoIba44HDSdaw0Pm3Fuc5Anc +V73IX9H3qdvWdyXwQH+0OLqcB09If0hifHEnChuD1HAJYMRIk0ylGs7W3ftSvN1e +mJj3SJLAKKwhxN5SuHGJBL5st1ZT6/cM/ksUlUWPxMhlGoFBfqte6Xb+D2/z7XvA +n2X60TcPAgMBAAECggEAU7LfL4ohgcZE072Exjjbif2rdhhhq9lJPjkTI555iN6e +rpLLNu+kk+fsY+c3P2/oBnqWZE3SML+XiXb646d5Ds+opP1BQXGxOl606Wo5pjyV +aK+Z6KfveqVTGfE0ZCiM70SVea93Mtpvk1DIFAT5q8zY4r76bTIm7KEN+Uf9C5g6 +THosL87Oo6nNVzYKSu5bwIyzbgUbbchX14DS7SAdRN0jUo0v8YOtYLNPiwOHoxuW +aTSeP6BKgw8YOiEsl0VXMI6DESvt/SP2zLx5N4B89sxJpzn4ZRrO0r07tY56QZex +n6gmmuxD440kreKLzE2erU+DYWpWU8O3R77nZFGysQKBgQD9zdsKqqe4XJcSYhHY +X7e7mXTM3Wm1I2HKPfaZ1V6PHiX5PGlK5dqGZMhT6quwZpTqV1Zx2Vhthj6YXAwY +Ka2bEnZQhw4umZOKzmiMSkFxDZQ/wfTzBOuGIdSsFk2387U1Q7hCwxZ2U5C+x+4S ++gfeISKeojpCxjk/qbIhdppK3wKBgQDAgnOGT1AWpfDNvGSxNq+vjuevFqlXbYjz +PE3jUF3IN/7iYJ2I5C43FoGl37BCxV2ZzxGIfvEu1fuI0+ZzmZdhjz4cpWkrIGf/ +y36UwLcxhfX+hmScqAQi8IrK+EGir7P4I8zlPH9gdhZGt7zP15EkCNo1OOoJAnMp +gBkYQQ/J0QKBgGd8Yk3NG6n+htLGDgStsprZjVhjB1EGZj8yWLSM3Yt5fX5MdZpG +cn3N5ijhTLQWf621gtfVCUtPK4KwNXY8uD68nmVjTBMQJ6q3UsWxGVHheYstqJTW +cro0XST1yyawRji7rgv6w9PnauN/XcF7FW4rEJSiDSNg88LTjIA8fdj9AoGAFjBz +JG4L6zBhWzV13b9R7MhqCBJynnMvr+mpiKQAy005AdrlDZxPf2YGt5na9TdOnKXz +fWo0XpOnlJPoIjb37fTW0fJ29tObaS6JfpfgBcNNIXNYMX5kS6qyNMb8ucXK1rU5 +rsqUXAgAdVJEXyiXwDGNBUl0IGm54HS1b8hAC6ECgYEAz1+mbr7Q37mjE+Z4+7rZ +zYe7plbcWn0wwPuhHC+18plqmQlsY6mbCsNXAwMyeW9/yDIsIfx7Xr9y/dTF3pCA +KfRhXvhS5hbDJatqkcSkGePbtOZuSPE8sMcFEQUAOgWF9aEyQ8VstfYWcXvOn8J6 +p/NjOzj9eM5NX2tFsIvHlAQ= -----END PRIVATE KEY----- diff --git a/client/src/test/java/com/influxdb/client/tls/client.p12 b/client/src/test/java/com/influxdb/client/tls/client.p12 index 3472fb0687dbc4c581edf31c9f064d5b44d36b27..6322a62b798d5a4969a9b5ea904cc67cd4fe3483 100644 GIT binary patch delta 2418 zcmV-&361vp6#5j9YY=Ub@L*0V2RM{wQAVd^$p?{pA%BbFJ0sw78_*ixuC@^pZL z1JJE#k6snW@$l{GpOEt%3}LF&T`~Bunjf)F{Y55vO^w;!>d+oldMUACX*jE+ocq?P ziHO;nESV)=0a=C|U+s=TFKM{I;I56Fa*Q0}NfFyVN!GBMCL8W=*VI<#cU=Z>p>`Sa zhuq=pzJKE!>JXSB2|fe~t$Q=BjNQdyiBWwJGgHu|i)3F(goeI}gB)gG`8vBjD3<`m zlD+|h88I4*j-utCyIPCM!DWF^s3Vep4(ew_?EEr7{;a7d(CIpOu+mv+%Xp@4#Zl-K z#~uexAnq4Crb%u^Mz~bJWS$zkWINk&)Vj{&7NKw#O!|kg%o%n7+Mx%M(9)$p6nAEh&Y^g2)%cS6_~!p z#I~p8yq3r3EgTwfi@qfH5ts|$*AiPQO-%?tdzq|ABaOxCMisQfbUkXQcbzFIO3HJV z;eSQ-$r#K2y*G8<(5}vFCxSI+=+;Hjfok62Y*e^o%ESR4@c_)ZqFinXHEB}e2O+1} zz#{?%3z)+cu;CHC*CSH%DCUv2o)?uPYFan_)-(pYR@rwpaKx{2f0iI=|;Po ziw-+x)z)=cGbzgKZ7S6-qn11F9eJ+^nSZp^=MRZYNLcyL`TZ00E*Y%~+$tjg)C%kg z_)kHb5Uk)X4=G?=J3UY^L*0;qk_8bM6J5A8{PU_!GsShO zKiXs!>r0?M5zyk?#Xw{Mxo2QbmUE=lGLgQk+LPaT=cLqHc>20WYuYm8F@qzn<7MS` zN(YG90RS8Cn542<(-zNNcq6~go~n?L z<7@(@N6@~~?hAmesJxcpa<-gN*9!Cgx=f5mwfeLX@pYEjxi`aTzJCDCSfcRC3835M z6*~lB^&6$v(rIRoW|yap<=>2&s*YyXIdqPL!`V#=ka*mZ+N`DE8rkViFHwA`% zB#M@FPnVV3c1PU6TYn+DvaG1y!+CN2MGRhcc@8w8Wp2Ti!71NB4NCotnu`bEo8E#z z_*w{Na8Z2X*N!zp)Lkww6-Fk3aS;a~vpPx?u%yt$se%2Tk+Oc6B80oq4Y?Rmp+XT_ zl35-q7n&=IN0kYIwUDRt{JWufK!2D0hU9$LFo;l?lpifn34f1!+nfsqXT~|sF=h-KxR*Dmhg}Zo7-nt|AwJ>!42GLVE8OP#0W_^RDYrycEZ>{Zmui?KbOxiT0_xv zS$>}I0T_mV^x{tU$dw&ES}PRdr{Q)$z1@``QIU+I+FsY1IwlR@+5M#dnU8N*>ut-+ zL1qp!B^n;N8JkgMjr_0qYdwwT9m0Iz5Lok%!}X@H6>AH&KFHXz)JxIT9v=Pv&MauXUy)G~qEr?-{)n;b2`^Ni~LBQU9bzF-63_ z25T@u1@MN%UXr$;rS&jb2v1Gr1n_8m6%Lh7$zo)|_*17MOdT(*prpIfv+rYt;JqW;3Kl!gpDA^S zO!q_s#z7d_+1^+p&AUT!+Y`y*zGbz}d~$V{(})jm%1uyXTLI)`&r+jQ! zhvWtb3K=(`!bqLN8tRBD-raK}JXK5K^xS(To0}z?a~hX1L@*r&2`Yw2hW8Bt2^299 z9+UeCAQX(i)Y9AvB2EX=E*!rxU6u05T=$bN3Kcf-68KQbjo87uIYAZv>VyL!F7H)~ kVEfg<^#6#Q*>R delta 2418 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 RKzzjB4taYS3!?%82mmf^t8oAT From 37fd0ba559a4cef8e8575b96c1c31f639c80075b Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Tue, 29 Sep 2026 22:43:39 +0700 Subject: [PATCH 3/3] feat: support tls --- CHANGELOG.md | 2 +- .../main/java/com/influxdb/utils/TlsUtils.java | 16 +++++++++++----- .../influxdb/client/InfluxDBClientOptions.java | 5 ++++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b78334d5ecf..72f2952807f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ### Features -- [#948](https://github.com/influxdata/influxdb-client-java/pull/948): Support TLS and mTls configurations. +- [#948](https://github.com/influxdata/influxdb-client-java/pull/948): Support TLS and mTLS configurations. ### Dependencies diff --git a/client-utils/src/main/java/com/influxdb/utils/TlsUtils.java b/client-utils/src/main/java/com/influxdb/utils/TlsUtils.java index b6afaf47bea..e386c37806d 100644 --- a/client-utils/src/main/java/com/influxdb/utils/TlsUtils.java +++ b/client-utils/src/main/java/com/influxdb/utils/TlsUtils.java @@ -121,13 +121,17 @@ public static KeyManagerFactory createKmfP12(@Nonnull final String path, public static KeyManagerFactory createKmf(@Nonnull final String certPath, @Nonnull final String keyPath) throws Exception { - X509Certificate certificate = TlsUtils.loadCertificate(certPath); + java.util.Collection certificateChain; + try (FileInputStream fis = new FileInputStream(certPath)) { + certificateChain = CertificateFactory.getInstance(X509).generateCertificates(fis); + } + PrivateKey privateKey = TlsUtils.loadPrivateKey(keyPath); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null, null); - keyStore.setKeyEntry("alias", privateKey, null, new Certificate[]{certificate}); + keyStore.setKeyEntry("alias", privateKey, null, certificateChain.toArray(new Certificate[0])); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(keyStore, null); @@ -163,10 +167,12 @@ public static TrustManagerFactory createTmf(@Nonnull final String path, KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + CertificateFactory certFactory = CertificateFactory.getInstance(X509); try (FileInputStream fis = new FileInputStream(path)) { - X509Certificate cert = (X509Certificate) certFactory.generateCertificate(fis); - trustStore.setCertificateEntry("alias", cert); + int alias = 0; + for (Certificate certificate : certFactory.generateCertificates(fis)) { + trustStore.setCertificateEntry("alias-" + alias++, certificate); + } } tmf.init(trustStore); } else { diff --git a/client/src/main/java/com/influxdb/client/InfluxDBClientOptions.java b/client/src/main/java/com/influxdb/client/InfluxDBClientOptions.java index b8d8250ce9a..df9ea3e1c1e 100644 --- a/client/src/main/java/com/influxdb/client/InfluxDBClientOptions.java +++ b/client/src/main/java/com/influxdb/client/InfluxDBClientOptions.java @@ -670,7 +670,10 @@ public InfluxDBClientOptions build() { .protocols(Collections.singletonList(Protocol.HTTP_1_1)); } - configureTls(okHttpClient); + HttpUrl parsedUrl = HttpUrl.parse(url); + if (parsedUrl != null && parsedUrl.isHttps()) { + configureTls(okHttpClient); + } if (logLevel == null) { logLevel = LogLevel.NONE;