Skip to content

Commit

Permalink
Added a (Key/Trust)StoreOptions configuration properties
Browse files Browse the repository at this point in the history
  • Loading branch information
mskacelik committed Sep 26, 2024
1 parent 485dc50 commit 1dd98ec
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,24 @@

import io.smallrye.graphql.client.impl.GraphQLClientConfiguration;
import io.smallrye.graphql.client.vertx.ssl.SSLTools;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.net.JksOptions;
import io.vertx.core.net.KeyCertOptions;
import io.vertx.core.net.ProxyOptions;
import io.vertx.core.net.SSLOptions;
import io.vertx.core.net.TrustOptions;

public class VertxClientOptionsHelper {

public static void applyConfigToVertxOptions(HttpClientOptions options, GraphQLClientConfiguration configuration) {
if (options.getTrustStoreOptions() == null && configuration.getTrustStore() != null) {
configure(options, configuration);
TrustOptions tlsTrustStoreOptions = (TrustOptions) configuration.getTlsTrustStoreOptions();
KeyCertOptions tlsKeyStoreOptions = (KeyCertOptions) configuration.getTlsKeyStoreOptions();
if (tlsTrustStoreOptions != null) {
options.setSsl(true);
options.setTrustOptions(tlsTrustStoreOptions);
} else if (options.getTrustStoreOptions() == null && configuration.getTrustStore() != null) { // deprecated in Quarkus
options.setSsl(true);
JksOptions trustStoreOptions = new JksOptions();
KeyStore trustStore = SSLTools.createKeyStore(configuration.getTrustStore(),
Expand All @@ -21,8 +31,10 @@ public static void applyConfigToVertxOptions(HttpClientOptions options, GraphQLC
trustStoreOptions.setPassword(new String(configuration.getTrustStorePassword()));
options.setTrustStoreOptions(trustStoreOptions);
}

if (options.getKeyStoreOptions() == null && configuration.getKeyStore() != null) {
if (tlsKeyStoreOptions != null) {
options.setSsl(true);
options.setKeyCertOptions(tlsKeyStoreOptions);
} else if (options.getKeyStoreOptions() == null && configuration.getKeyStore() != null) { // deprecated in Quarkus
options.setSsl(true);
JksOptions keyStoreOptions = new JksOptions();
KeyStore keyStore = SSLTools.createKeyStore(configuration.getKeyStore(),
Expand All @@ -45,10 +57,26 @@ public static void applyConfigToVertxOptions(HttpClientOptions options, GraphQLC
if (configuration.getMaxRedirects() != null) {
options.setMaxRedirects(configuration.getMaxRedirects());
}
}

if (options.isSsl()) {
// TODO: this is not supported yet
private static void configure(HttpClientOptions options, GraphQLClientConfiguration graphQLClientConfiguration) {
options.setForceSni(graphQLClientConfiguration.usesSni() != null && graphQLClientConfiguration.usesSni());
if (graphQLClientConfiguration.getHostnameVerificationAlgorithm() == null
|| graphQLClientConfiguration.getHostnameVerificationAlgorithm().equals("NONE")) {
options.setVerifyHost(false);
}
SSLOptions sslOptions = (SSLOptions) graphQLClientConfiguration.getSslOptions();
if (sslOptions != null) {
options.setSslHandshakeTimeout(sslOptions.getSslHandshakeTimeout());
options.setSslHandshakeTimeoutUnit(sslOptions.getSslHandshakeTimeoutUnit());
for (String suite : sslOptions.getEnabledCipherSuites()) {
options.addEnabledCipherSuite(suite);
}
for (Buffer buffer : sslOptions.getCrlValues()) {
options.addCrlValue(buffer);
}
options.setEnabledSecureTransportProtocols(sslOptions.getEnabledSecureTransportProtocols());
options.setUseAlpn(sslOptions.isUseAlpn());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ public void serverAuthentication_correctTruststore() throws Exception {
System.setProperty("ts/mp-graphql/truststore", "classpath:ssl/client.pkcs12.truststore");
System.setProperty("ts/mp-graphql/truststorePassword", "clienttruststorepassword");
System.setProperty("ts/mp-graphql/truststoreType", "PKCS12");

try (MyClient client = TypesafeGraphQLClientBuilder.newBuilder()
.configKey("ts")
.endpoint("https://127.0.0.1:" + server.actualPort())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,33 @@ public class GraphQLClientConfiguration {
*/
private String keyStoreType;

/**
* The key store options, already contains key store.
*/
private Object tlsKeyStoreOptions;

/**
* The trust store options, already contains trust store.
*/
private Object tlsTrustStoreOptions;

/**
* SSL options for connection.
*/
private Object sslOptions;

/**
* Indicates whether Server Name Indication (SNI) is enabled for this connection.
* When SNI is enabled, the client sends the server name during the TLS handshake,
* allowing the server to select the appropriate certificate based on the hostname.
*/
private Boolean usesSni;

/**
* Specifies the algorithm used for hostname verification during the TLS handshake.
*/
private String hostnameVerificationAlgorithm;

/**
* Hostname of the proxy to use.
*/
Expand Down Expand Up @@ -273,6 +300,46 @@ public void setAllowUnexpectedResponseFields(Boolean allowUnexpectedResponseFiel
this.allowUnexpectedResponseFields = allowUnexpectedResponseFields;
}

public Object getTlsKeyStoreOptions() {
return tlsKeyStoreOptions;
}

public void setTlsKeyStoreOptions(Object tlsKeyStoreOptions) {
this.tlsKeyStoreOptions = tlsKeyStoreOptions;
}

public Object getTlsTrustStoreOptions() {
return tlsTrustStoreOptions;
}

public void setTlsTrustStoreOptions(Object tlsTrustStoreOptions) {
this.tlsTrustStoreOptions = tlsTrustStoreOptions;
}

public Boolean usesSni() {
return usesSni;
}

public void setUsesSni(Boolean usesSni) {
this.usesSni = usesSni;
}

public String getHostnameVerificationAlgorithm() {
return hostnameVerificationAlgorithm;
}

public void setHostnameVerificationAlgorithm(String hostnameVerificationAlgorithm) {
this.hostnameVerificationAlgorithm = hostnameVerificationAlgorithm;
}

public Object getSslOptions() {
return sslOptions;
}

public void setSslOptions(Object sslOptions) {
this.sslOptions = sslOptions;
}

/**
* Merge the `other` configuration into this one. Values in `other` take precedence.
* This method has to be idempotent because it can be called multiple times to allow for changes in configuration.
Expand Down Expand Up @@ -350,6 +417,21 @@ public GraphQLClientConfiguration merge(GraphQLClientConfiguration other) {
if (other.allowUnexpectedResponseFields != null) {
this.allowUnexpectedResponseFields = other.allowUnexpectedResponseFields;
}
if (other.tlsKeyStoreOptions != null) {
this.tlsKeyStoreOptions = other.tlsKeyStoreOptions;
}
if (other.tlsTrustStoreOptions != null) {
this.tlsTrustStoreOptions = other.tlsTrustStoreOptions;
}
if (other.usesSni != null) {
this.usesSni = other.usesSni;
}
if (other.hostnameVerificationAlgorithm != null) {
this.hostnameVerificationAlgorithm = other.hostnameVerificationAlgorithm;
}
if (other.sslOptions != null) {
this.sslOptions = other.sslOptions;
}
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ private GraphQLClientConfiguration readConfigurationByKey(String clientName) {
.ifPresent(configuration::setExecuteSingleOperationsOverWebsocket);
mpConfig.getOptionalValue(clientName + "/mp-graphql/allowUnexpectedResponseFields", Boolean.class)
.ifPresent(configuration::setAllowUnexpectedResponseFields);
mpConfig.getOptionalValue(clientName + "/mp-graphql/hostnameVerificationAlgorithm", String.class)
.ifPresent(configuration::setHostnameVerificationAlgorithm);
mpConfig.getOptionalValue(clientName + "/mp-graphql/usesSni", Boolean.class)
.ifPresent(configuration::setUsesSni);
return configuration;
}

Expand Down

0 comments on commit 1dd98ec

Please sign in to comment.