Skip to content

Commit 16c7a55

Browse files
committed
Centralize SSL context building in TransportOptions
Extract duplicated SSL context construction from OAuthAuthenticator, OpenId, and ApiClient into TransportOptions.buildSSLContext().
1 parent 1dd95e3 commit 16c7a55

4 files changed

Lines changed: 90 additions & 147 deletions

File tree

‎src/main/java/com/zitadel/ApiClient.java‎

Lines changed: 5 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -113,55 +113,13 @@ private static CloseableHttpClient buildHttpClient(TransportOptions transportOpt
113113
try {
114114
HttpClientBuilder builder = HttpClients.custom().setUserAgent(USER_AGENT);
115115

116-
if (transportOptions.isInsecure()) {
117-
SSLContext sslContext = SSLContext.getInstance("TLS");
118-
sslContext.init(null, new TrustManager[]{new X509TrustManager() {
119-
@Override
120-
public void checkClientTrusted(X509Certificate[] chain, String authType) {
121-
// trust all
122-
}
123-
124-
@Override
125-
public void checkServerTrusted(X509Certificate[] chain, String authType) {
126-
// trust all
127-
}
128-
129-
@Override
130-
public X509Certificate[] getAcceptedIssuers() {
131-
return new X509Certificate[0];
132-
}
133-
}}, null);
134-
SSLConnectionSocketFactoryBuilder sslSocketFactoryBuilder = SSLConnectionSocketFactoryBuilder.create()
135-
.setSslContext(sslContext)
136-
.setHostnameVerifier(NoopHostnameVerifier.INSTANCE);
137-
builder.setConnectionManager(PoolingHttpClientConnectionManagerBuilder.create()
138-
.setSSLSocketFactory(sslSocketFactoryBuilder.build())
139-
.build());
140-
} else if (transportOptions.getCaCertPath() != null) {
141-
CertificateFactory cf = CertificateFactory.getInstance("X.509");
142-
java.security.cert.Certificate caCert;
143-
try (FileInputStream fis = new FileInputStream(transportOptions.getCaCertPath())) {
144-
caCert = cf.generateCertificate(fis);
145-
}
146-
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
147-
ks.load(null, null);
148-
ks.setCertificateEntry("custom-ca", caCert);
149-
TrustManagerFactory defaultTmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
150-
defaultTmf.init((KeyStore) null);
151-
int certIndex = 0;
152-
for (javax.net.ssl.TrustManager tm : defaultTmf.getTrustManagers()) {
153-
if (tm instanceof javax.net.ssl.X509TrustManager) {
154-
for (java.security.cert.X509Certificate cert : ((javax.net.ssl.X509TrustManager) tm).getAcceptedIssuers()) {
155-
ks.setCertificateEntry("default-" + certIndex++, cert);
156-
}
157-
}
158-
}
159-
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
160-
tmf.init(ks);
161-
SSLContext sslContext = SSLContext.getInstance("TLS");
162-
sslContext.init(null, tmf.getTrustManagers(), null);
116+
SSLContext sslContext = transportOptions.buildSSLContext();
117+
if (sslContext != null) {
163118
SSLConnectionSocketFactoryBuilder sslSocketFactoryBuilder = SSLConnectionSocketFactoryBuilder.create()
164119
.setSslContext(sslContext);
120+
if (transportOptions.isInsecure()) {
121+
sslSocketFactoryBuilder.setHostnameVerifier(NoopHostnameVerifier.INSTANCE);
122+
}
165123
builder.setConnectionManager(PoolingHttpClientConnectionManagerBuilder.create()
166124
.setSSLSocketFactory(sslSocketFactoryBuilder.build())
167125
.build());

‎src/main/java/com/zitadel/TransportOptions.java‎

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
package com.zitadel;
22

3+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4+
35
import javax.annotation.Nullable;
6+
import javax.net.ssl.SSLContext;
7+
import javax.net.ssl.TrustManager;
8+
import javax.net.ssl.TrustManagerFactory;
9+
import javax.net.ssl.X509TrustManager;
10+
import java.io.FileInputStream;
11+
import java.io.IOException;
12+
import java.security.GeneralSecurityException;
13+
import java.security.KeyStore;
14+
import java.security.cert.CertificateFactory;
15+
import java.security.cert.X509Certificate;
416
import java.util.Collections;
517
import java.util.LinkedHashMap;
618
import java.util.Map;
@@ -75,6 +87,71 @@ public String getProxyUrl() {
7587
return proxyUrl;
7688
}
7789

90+
/**
91+
* Builds an {@link SSLContext} from these transport options.
92+
*
93+
* <p>If insecure mode is enabled, returns a trust-all SSLContext.
94+
* If a custom CA cert path is set, returns an SSLContext that trusts
95+
* both the custom CA and the system default CAs.
96+
* Otherwise returns {@code null} (use JVM defaults).
97+
*
98+
* @return the configured SSLContext, or {@code null} if no custom SSL is needed.
99+
* @throws GeneralSecurityException if SSL context creation fails.
100+
* @throws IOException if the CA cert file cannot be read.
101+
*/
102+
@Nullable
103+
@SuppressFBWarnings("PATH_TRAVERSAL_IN")
104+
public SSLContext buildSSLContext() throws GeneralSecurityException, IOException {
105+
if (insecure) {
106+
SSLContext sslContext = SSLContext.getInstance("TLS");
107+
sslContext.init(null, new TrustManager[]{new InsecureTrustManager()}, null);
108+
return sslContext;
109+
} else if (caCertPath != null) {
110+
CertificateFactory cf = CertificateFactory.getInstance("X.509");
111+
java.security.cert.Certificate caCert;
112+
try (FileInputStream fis = new FileInputStream(caCertPath)) {
113+
caCert = cf.generateCertificate(fis);
114+
}
115+
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
116+
ks.load(null, null);
117+
ks.setCertificateEntry("custom-ca", caCert);
118+
TrustManagerFactory defaultTmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
119+
defaultTmf.init((KeyStore) null);
120+
int certIndex = 0;
121+
for (TrustManager tm : defaultTmf.getTrustManagers()) {
122+
if (tm instanceof X509TrustManager) {
123+
for (X509Certificate cert : ((X509TrustManager) tm).getAcceptedIssuers()) {
124+
ks.setCertificateEntry("default-" + certIndex++, cert);
125+
}
126+
}
127+
}
128+
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
129+
tmf.init(ks);
130+
SSLContext sslContext = SSLContext.getInstance("TLS");
131+
sslContext.init(null, tmf.getTrustManagers(), null);
132+
return sslContext;
133+
}
134+
return null;
135+
}
136+
137+
@SuppressFBWarnings("WEAK_TRUST_MANAGER")
138+
private static final class InsecureTrustManager implements X509TrustManager {
139+
@Override
140+
public void checkClientTrusted(X509Certificate[] chain, String authType) {
141+
// trust all
142+
}
143+
144+
@Override
145+
public void checkServerTrusted(X509Certificate[] chain, String authType) {
146+
// trust all
147+
}
148+
149+
@Override
150+
public X509Certificate[] getAcceptedIssuers() {
151+
return new X509Certificate[0];
152+
}
153+
}
154+
78155
/**
79156
* Builder for constructing {@link TransportOptions} instances.
80157
*/

‎src/main/java/com/zitadel/auth/OAuthAuthenticator.java‎

Lines changed: 4 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,12 @@
1010

1111
import javax.annotation.Nullable;
1212
import javax.net.ssl.SSLContext;
13-
import javax.net.ssl.TrustManager;
14-
import javax.net.ssl.TrustManagerFactory;
15-
import javax.net.ssl.X509TrustManager;
16-
import java.io.FileInputStream;
1713
import java.io.IOException;
1814
import java.net.InetSocketAddress;
1915
import java.net.Proxy;
2016
import java.net.URI;
2117
import java.net.URISyntaxException;
2218
import java.net.URL;
23-
import java.security.KeyStore;
24-
import java.security.cert.CertificateFactory;
2519
import java.security.cert.X509Certificate;
2620
import java.time.Instant;
2721
import java.time.temporal.ChronoUnit;
@@ -127,35 +121,12 @@ protected Token getToken(ClientAuthentication authentication) throws ZitadelExce
127121
}
128122

129123
// Apply SSL settings
130-
if (transportOptions.isInsecure()) {
131-
SSLContext sslContext = SSLContext.getInstance("TLS");
132-
sslContext.init(null, new TrustManager[]{new InsecureTrustManager()}, null);
124+
SSLContext sslContext = transportOptions.buildSSLContext();
125+
if (sslContext != null) {
133126
httpRequest.setSSLSocketFactory(sslContext.getSocketFactory());
134-
httpRequest.setHostnameVerifier((h, s) -> true);
135-
} else if (transportOptions.getCaCertPath() != null) {
136-
CertificateFactory cf = CertificateFactory.getInstance("X.509");
137-
java.security.cert.Certificate caCert;
138-
try (FileInputStream fis = new FileInputStream(transportOptions.getCaCertPath())) {
139-
caCert = cf.generateCertificate(fis);
127+
if (transportOptions.isInsecure()) {
128+
httpRequest.setHostnameVerifier((h, s) -> true);
140129
}
141-
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
142-
ks.load(null, null);
143-
ks.setCertificateEntry("custom-ca", caCert);
144-
TrustManagerFactory defaultTmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
145-
defaultTmf.init((KeyStore) null);
146-
int certIndex = 0;
147-
for (TrustManager tm : defaultTmf.getTrustManagers()) {
148-
if (tm instanceof X509TrustManager) {
149-
for (X509Certificate cert : ((X509TrustManager) tm).getAcceptedIssuers()) {
150-
ks.setCertificateEntry("default-" + certIndex++, cert);
151-
}
152-
}
153-
}
154-
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
155-
tmf.init(ks);
156-
SSLContext sslContext = SSLContext.getInstance("TLS");
157-
sslContext.init(null, tmf.getTrustManagers(), null);
158-
httpRequest.setSSLSocketFactory(sslContext.getSocketFactory());
159130
}
160131

161132
// Apply default headers
@@ -212,24 +183,6 @@ private boolean isExpired() {
212183
}
213184
}
214185

215-
@SuppressFBWarnings("WEAK_TRUST_MANAGER")
216-
private static final class InsecureTrustManager implements X509TrustManager {
217-
@Override
218-
public void checkClientTrusted(X509Certificate[] chain, String authType) {
219-
// trust all
220-
}
221-
222-
@Override
223-
public void checkServerTrusted(X509Certificate[] chain, String authType) {
224-
// trust all
225-
}
226-
227-
@Override
228-
public X509Certificate[] getAcceptedIssuers() {
229-
return new X509Certificate[0];
230-
}
231-
}
232-
233186
protected abstract static class OAuthAuthenticatorBuilder<
234187
T extends OAuthAuthenticatorBuilder<?>> {
235188

‎src/main/java/com/zitadel/auth/OpenId.java‎

Lines changed: 4 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,14 @@
88

99
import javax.net.ssl.HttpsURLConnection;
1010
import javax.net.ssl.SSLContext;
11-
import javax.net.ssl.TrustManager;
12-
import javax.net.ssl.TrustManagerFactory;
13-
import javax.net.ssl.X509TrustManager;
1411
import java.io.BufferedReader;
15-
import java.io.FileInputStream;
1612
import java.io.IOException;
1713
import java.io.InputStreamReader;
1814
import java.net.HttpURLConnection;
1915
import java.net.InetSocketAddress;
2016
import java.net.Proxy;
2117
import java.net.URL;
2218
import java.nio.charset.StandardCharsets;
23-
import java.security.KeyStore;
24-
import java.security.cert.CertificateFactory;
25-
import java.security.cert.X509Certificate;
2619
import java.util.Map;
2720

2821
public class OpenId {
@@ -59,50 +52,12 @@ public OpenId(String hostname, TransportOptions transportOptions) {
5952

6053
if (connection instanceof HttpsURLConnection) {
6154
HttpsURLConnection httpsConn = (HttpsURLConnection) connection;
62-
if (opts.isInsecure()) {
63-
SSLContext sslContext = SSLContext.getInstance("TLS");
64-
sslContext.init(null, new TrustManager[]{new X509TrustManager() {
65-
@Override
66-
public void checkClientTrusted(X509Certificate[] chain, String authType) {
67-
// trust all
68-
}
69-
70-
@Override
71-
public void checkServerTrusted(X509Certificate[] chain, String authType) {
72-
// trust all
73-
}
74-
75-
@Override
76-
public X509Certificate[] getAcceptedIssuers() {
77-
return new X509Certificate[0];
78-
}
79-
}}, null);
55+
SSLContext sslContext = opts.buildSSLContext();
56+
if (sslContext != null) {
8057
httpsConn.setSSLSocketFactory(sslContext.getSocketFactory());
81-
httpsConn.setHostnameVerifier((h, s) -> true);
82-
} else if (opts.getCaCertPath() != null) {
83-
CertificateFactory cf = CertificateFactory.getInstance("X.509");
84-
java.security.cert.Certificate caCert;
85-
try (FileInputStream fis = new FileInputStream(opts.getCaCertPath())) {
86-
caCert = cf.generateCertificate(fis);
58+
if (opts.isInsecure()) {
59+
httpsConn.setHostnameVerifier((h, s) -> true);
8760
}
88-
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
89-
ks.load(null, null);
90-
ks.setCertificateEntry("custom-ca", caCert);
91-
TrustManagerFactory defaultTmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
92-
defaultTmf.init((KeyStore) null);
93-
int certIndex = 0;
94-
for (TrustManager tm : defaultTmf.getTrustManagers()) {
95-
if (tm instanceof X509TrustManager) {
96-
for (java.security.cert.X509Certificate cert : ((X509TrustManager) tm).getAcceptedIssuers()) {
97-
ks.setCertificateEntry("default-" + certIndex++, cert);
98-
}
99-
}
100-
}
101-
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
102-
tmf.init(ks);
103-
SSLContext sslContext = SSLContext.getInstance("TLS");
104-
sslContext.init(null, tmf.getTrustManagers(), null);
105-
httpsConn.setSSLSocketFactory(sslContext.getSocketFactory());
10661
}
10762
}
10863

0 commit comments

Comments
 (0)