Skip to content

Commit

Permalink
SSL support for Reactive Pg Client
Browse files Browse the repository at this point in the history
Fixes #552
  • Loading branch information
tsegismont committed May 19, 2020
1 parent c06ab1d commit 73acac4
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 2 deletions.
3 changes: 2 additions & 1 deletion docs/src/main/asciidoc/native-and-ssl.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ As SSL is de facto the standard nowadays, we decided to enable its support autom
* the MongoDB extension (`quarkus-mongodb-client`),
* the Neo4j extension (`quarkus-neo4j`),
* the OAuth2 extension (`quarkus-elytron-security-oauth2`),
* the REST client extension (`quarkus-rest-client`).
* the REST client extension (`quarkus-rest-client`),
* the Reactive client for PostgreSQL extension (`quarkus-reactive-pg-client`).


As long as you have one of those extensions in your project, the SSL support will be enabled by default.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.ServiceStartBuildItem;
import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
Expand Down Expand Up @@ -43,6 +44,7 @@ ServiceStartBuildItem build(BuildProducer<FeatureBuildItem> feature, BuildProduc
PgPoolRecorder recorder,
VertxBuildItem vertx,
BeanContainerBuildItem beanContainer, ShutdownContextBuildItem shutdown,
BuildProducer<ExtensionSslNativeSupportBuildItem> sslNativeSupport,
DataSourcesBuildTimeConfig dataSourcesBuildTimeConfig, DataSourcesRuntimeConfig dataSourcesRuntimeConfig,
DataSourceReactiveBuildTimeConfig dataSourceReactiveBuildTimeConfig,
DataSourceReactiveRuntimeConfig dataSourceReactiveRuntimeConfig,
Expand All @@ -68,6 +70,9 @@ ServiceStartBuildItem build(BuildProducer<FeatureBuildItem> feature, BuildProduc
legacyDataSourcesRuntimeConfig, legacyDataSourceReactivePostgreSQLConfig, isLegacy,
shutdown)));

// Enable SSL support by default
sslNativeSupport.produce(new ExtensionSslNativeSupportBuildItem(FeatureBuildItem.REACTIVE_PG_CLIENT));

return serviceStart;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;
import io.quarkus.vertx.core.runtime.config.JksConfiguration;
import io.quarkus.vertx.core.runtime.config.PemKeyCertConfiguration;
import io.quarkus.vertx.core.runtime.config.PemTrustCertConfiguration;
import io.quarkus.vertx.core.runtime.config.PfxConfiguration;
import io.vertx.pgclient.SslMode;

@ConfigRoot(name = "datasource.reactive.postgresql", phase = ConfigPhase.RUN_TIME)
public class DataSourceReactivePostgreSQLConfig {
Expand All @@ -21,4 +26,49 @@ public class DataSourceReactivePostgreSQLConfig {
*/
@ConfigItem
public OptionalInt pipeliningLimit;

/**
* SSL operating mode of the client.
* <p>
* See <a href="https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-PROTECTION">Protection Provided in
* Different Modes</a>.
*/
@ConfigItem
public Optional<SslMode> sslMode;

/**
* Trust configuration in the PEM format.
*/
@ConfigItem
public PemTrustCertConfiguration trustPem;

/**
* Trust configuration in the JKS format.
*/
@ConfigItem
public JksConfiguration trustJks;

/**
* Trust configuration in the PFX format.
*/
@ConfigItem
public PfxConfiguration trustPfx;

/**
* Key/cert configuration in the PEM format.
*/
@ConfigItem
public PemKeyCertConfiguration keyCertPem;

/**
* Key/cert configuration in the JKS format.
*/
@ConfigItem
public JksConfiguration keyCertJks;

/**
* Key/cert configuration in the PFX format.
*/
@ConfigItem
public PfxConfiguration keyCertPfx;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static io.quarkus.credentials.CredentialsProvider.PASSWORD_PROPERTY_NAME;
import static io.quarkus.credentials.CredentialsProvider.USER_PROPERTY_NAME;
import static io.quarkus.vertx.core.runtime.SSLConfigHelper.*;

import java.util.Map;

Expand Down Expand Up @@ -121,6 +122,18 @@ private PgConnectOptions toPgConnectOptions(DataSourceRuntimeConfig dataSourceRu
pgConnectOptions.setPipeliningLimit(dataSourceReactivePostgreSQLConfig.pipeliningLimit.getAsInt());
}

if (dataSourceReactivePostgreSQLConfig.sslMode.isPresent()) {
pgConnectOptions.setSslMode(dataSourceReactivePostgreSQLConfig.sslMode.get());
}

configurePemTrustOptions(pgConnectOptions, dataSourceReactivePostgreSQLConfig.trustPem);
configureJksTrustOptions(pgConnectOptions, dataSourceReactivePostgreSQLConfig.trustJks);
configurePfxTrustOptions(pgConnectOptions, dataSourceReactivePostgreSQLConfig.trustPfx);

configurePemKeyCertOptions(pgConnectOptions, dataSourceReactivePostgreSQLConfig.keyCertPem);
configureJksKeyCertOptions(pgConnectOptions, dataSourceReactivePostgreSQLConfig.keyCertJks);
configurePfxKeyCertOptions(pgConnectOptions, dataSourceReactivePostgreSQLConfig.keyCertPfx);

return pgConnectOptions;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package io.quarkus.vertx.core.runtime;

import java.util.regex.Pattern;

import io.quarkus.vertx.core.runtime.config.JksConfiguration;
import io.quarkus.vertx.core.runtime.config.PemKeyCertConfiguration;
import io.quarkus.vertx.core.runtime.config.PemTrustCertConfiguration;
import io.quarkus.vertx.core.runtime.config.PfxConfiguration;
import io.vertx.core.net.*;

public class SSLConfigHelper {

private static final Pattern COMMA_PATTERN = Pattern.compile(",");

public static void configurePemTrustOptions(TCPSSLOptions options, PemTrustCertConfiguration configuration) {
if (configuration.enabled) {
ensureTrustOptionsNotSet(options);
options.setTrustOptions(toPemTrustOptions(configuration));
}
}

private static PemTrustOptions toPemTrustOptions(PemTrustCertConfiguration configuration) {
PemTrustOptions pemTrustOptions = new PemTrustOptions();
if (configuration.certs.isPresent()) {
for (String cert : COMMA_PATTERN.split(configuration.certs.get())) {
pemTrustOptions.addCertPath(cert.trim());
}
}
return pemTrustOptions;
}

public static void configureJksTrustOptions(TCPSSLOptions options, JksConfiguration configuration) {
if (configuration.enabled) {
ensureTrustOptionsNotSet(options);
options.setTrustOptions(toJksOptions(configuration));
}
}

private static JksOptions toJksOptions(JksConfiguration configuration) {
JksOptions jksOptions = new JksOptions();
if (configuration.path.isPresent()) {
jksOptions.setPath(configuration.path.get());
}
if (configuration.password.isPresent()) {
jksOptions.setPassword(configuration.password.get());
}
return jksOptions;
}

public static void configurePfxTrustOptions(TCPSSLOptions options, PfxConfiguration configuration) {
if (configuration.enabled) {
ensureTrustOptionsNotSet(options);
options.setTrustOptions(toPfxOptions(configuration));
}
}

private static PfxOptions toPfxOptions(PfxConfiguration configuration) {
PfxOptions pfxOptions = new PfxOptions();
if (configuration.path.isPresent()) {
pfxOptions.setPath(configuration.path.get());
}
if (configuration.password.isPresent()) {
pfxOptions.setPassword(configuration.password.get());
}
return pfxOptions;
}

private static void ensureTrustOptionsNotSet(TCPSSLOptions options) {
if (options.getTrustOptions() != null) {
throw new IllegalArgumentException("Trust options have already been set");
}
}

public static void configurePemKeyCertOptions(TCPSSLOptions options, PemKeyCertConfiguration configuration) {
if (configuration.enabled) {
ensureKeyCertOptionsNotSet(options);
options.setKeyCertOptions(toPemKeyCertOptions(configuration));
}
}

private static KeyCertOptions toPemKeyCertOptions(PemKeyCertConfiguration configuration) {
PemKeyCertOptions pemKeyCertOptions = new PemKeyCertOptions();
if (configuration.certs.isPresent()) {
for (String cert : COMMA_PATTERN.split(configuration.certs.get())) {
pemKeyCertOptions.addCertPath(cert.trim());
}
}
if (configuration.keys.isPresent()) {
for (String cert : COMMA_PATTERN.split(configuration.keys.get())) {
pemKeyCertOptions.addKeyPath(cert.trim());
}
}
return pemKeyCertOptions;
}

public static void configureJksKeyCertOptions(TCPSSLOptions options, JksConfiguration configuration) {
if (configuration.enabled) {
ensureKeyCertOptionsNotSet(options);
options.setKeyCertOptions(toJksOptions(configuration));
}
}

public static void configurePfxKeyCertOptions(TCPSSLOptions options, PfxConfiguration configuration) {
if (configuration.enabled) {
ensureKeyCertOptionsNotSet(options);
options.setKeyCertOptions(toPfxOptions(configuration));
}
}

private static void ensureKeyCertOptionsNotSet(TCPSSLOptions options) {
if (options.getKeyCertOptions() != null) {
throw new IllegalArgumentException("Key cert options have already been set");
}
}

private SSLConfigHelper() {
// Utility
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
@ConfigGroup
public class JksConfiguration {

/**
* JKS config is disabled by default.
*/
@ConfigItem(name = ConfigItem.PARENT, defaultValue = "false")
public boolean enabled;

/**
* Path of the key file (JKS format).
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
@ConfigGroup
public class PemKeyCertConfiguration {

/**
* PEM Key/cert config is disabled by default.
*/
@ConfigItem(name = ConfigItem.PARENT, defaultValue = "false")
public boolean enabled;

/**
* Comma-separated list of the path to the key files (Pem format).
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
@ConfigGroup
public class PemTrustCertConfiguration {

/**
* PEM Trust config is disabled by default.
*/
@ConfigItem(name = ConfigItem.PARENT, defaultValue = "false")
public boolean enabled;

/**
* Comma-separated list of the trust certificate files (Pem format).
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@
public class PfxConfiguration {

/**
* Path to the key file (PFX format)
* PFX config is disabled by default.
*/
@ConfigItem(name = ConfigItem.PARENT, defaultValue = "false")
public boolean enabled;

/**
* Path to the key file (PFX format).
*/
@ConfigItem
public Optional<String> path;
Expand Down

0 comments on commit 73acac4

Please sign in to comment.