Skip to content

Commit bc1ae82

Browse files
authored
Merge pull request #76 from Altinity/74-add---insecure-flag-to-skip-ssl-certificate-verification
Added support for insecure mode, where certs are trusted and host name verification is disabled.
2 parents d56b849 + 27add4d commit bc1ae82

File tree

3 files changed

+58
-8
lines changed

3 files changed

+58
-8
lines changed

ice/src/main/java/com/altinity/ice/cli/Main.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ public String configFile() {
8181
scope = CommandLine.ScopeType.INHERIT)
8282
private String logLevel;
8383

84+
@CommandLine.Option(
85+
names = {"--insecure", "--ssl-no-verify"},
86+
description =
87+
"Skip SSL certificate verification (WARNING: insecure, use only for development)",
88+
scope = CommandLine.ScopeType.INHERIT)
89+
private boolean insecure;
90+
8491
private Main() {}
8592

8693
@CommandLine.Command(name = "check", description = "Check configuration.")
@@ -595,7 +602,19 @@ private RESTCatalog loadCatalog(String configFile) throws IOException {
595602
}
596603
}
597604

598-
RESTCatalog catalog = RESTCatalogFactory.create(caCrt);
605+
// Command-line flag takes precedence over config file
606+
// Default to true (verify SSL) unless explicitly disabled
607+
boolean sslVerify = !insecure;
608+
if (config.sslVerify() != null) {
609+
sslVerify = config.sslVerify() && !insecure;
610+
}
611+
612+
if (!sslVerify) {
613+
logger.warn(
614+
"SSL certificate verification is DISABLED. This is insecure and should only be used for development.");
615+
}
616+
617+
RESTCatalog catalog = RESTCatalogFactory.create(caCrt, sslVerify);
599618
var icebergConfig = config.toIcebergConfig();
600619
logger.debug(
601620
"Iceberg configuration: {}",

ice/src/main/java/com/altinity/ice/cli/internal/config/Config.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ public record Config(
2828
"PEM-encoded CA bundle (use base64: prefix to pass base64-encoded value)")
2929
String caCrt,
3030
@JsonPropertyDescription("Bearer token to authorizer requests with") String bearerToken,
31+
@JsonPropertyDescription(
32+
"Skip SSL certificate verification (WARNING: insecure, use only for development)")
33+
Boolean sslVerify,
3134
@JsonPropertyDescription(
3235
"/path/to/dir where to store downloaded files when `ice insert`ing from http:// & https://")
3336
String httpCacheDir,

ice/src/main/java/com/altinity/ice/cli/internal/iceberg/rest/RESTCatalogFactory.java

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,45 @@
1919
import java.security.cert.Certificate;
2020
import java.security.cert.CertificateException;
2121
import java.security.cert.CertificateFactory;
22+
import java.security.cert.X509Certificate;
2223
import java.util.Collection;
24+
import javax.net.ssl.HostnameVerifier;
2325
import javax.net.ssl.SSLContext;
26+
import javax.net.ssl.TrustManager;
2427
import javax.net.ssl.TrustManagerFactory;
28+
import javax.net.ssl.X509TrustManager;
2529
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
26-
import org.apache.hc.client5.http.ssl.HostnameVerificationPolicy;
2730
import org.apache.hc.client5.http.ssl.HttpsSupport;
31+
import org.apache.hc.client5.http.ssl.TlsSocketStrategy;
2832
import org.apache.iceberg.CatalogProperties;
2933
import org.apache.iceberg.catalog.SessionCatalog;
3034
import org.apache.iceberg.rest.HTTPClient;
3135
import org.apache.iceberg.rest.RESTCatalog;
3236

3337
public class RESTCatalogFactory {
3438

35-
public static RESTCatalog create(byte[] caCrt) {
36-
if (caCrt == null) {
39+
public static RESTCatalog create(byte[] caCrt, boolean sslVerify) {
40+
if (caCrt == null && sslVerify) {
3741
return new RESTCatalog();
3842
}
3943
SSLContext sslContext;
4044
try {
41-
sslContext = loadCABundle(caCrt);
45+
if (!sslVerify) {
46+
sslContext = createInsecureSSLContext();
47+
} else {
48+
sslContext = loadCABundle(caCrt);
49+
}
4250
} catch (CertificateException
4351
| KeyStoreException
4452
| IOException
4553
| NoSuchAlgorithmException
4654
| KeyManagementException e) {
4755
throw new RuntimeException(e);
4856
}
49-
var tlsSocketStrategy =
50-
new DefaultClientTlsStrategy(
51-
sslContext, HostnameVerificationPolicy.BOTH, HttpsSupport.getDefaultHostnameVerifier());
57+
HostnameVerifier hostnameVerifier =
58+
sslVerify ? HttpsSupport.getDefaultHostnameVerifier() : (hostname, session) -> true;
59+
TlsSocketStrategy tlsSocketStrategy =
60+
new DefaultClientTlsStrategy(sslContext, hostnameVerifier);
5261
return new RESTCatalog(
5362
SessionCatalog.SessionContext.createEmpty(),
5463
x ->
@@ -80,4 +89,23 @@ private static SSLContext loadCABundle(byte[] caCrt)
8089
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
8190
return sslContext;
8291
}
92+
93+
private static SSLContext createInsecureSSLContext()
94+
throws NoSuchAlgorithmException, KeyManagementException {
95+
TrustManager[] trustAllCerts =
96+
new TrustManager[] {
97+
new X509TrustManager() {
98+
public X509Certificate[] getAcceptedIssuers() {
99+
return new X509Certificate[0];
100+
}
101+
102+
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
103+
104+
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
105+
}
106+
};
107+
SSLContext sslContext = SSLContext.getInstance("TLS");
108+
sslContext.init(null, trustAllCerts, new SecureRandom());
109+
return sslContext;
110+
}
83111
}

0 commit comments

Comments
 (0)