credentialsProvider = Optional.empty();
+
+ /**
+ * The credentials provider bean name.
+ *
+ * It is the {@code @Named} value of the credentials provider bean. It is used to discriminate if multiple
+ * CredentialsProvider beans are available.
+ * It is recommended to set this property even if there is only one credentials provider currently available
+ * to ensure the same provider is always found in deployments where more than one provider may be available.
+ */
+ @ConfigItem
+ @ConvertWith(TrimmedStringConverter.class)
+ public Optional credentialsProviderName = Optional.empty();
+
/**
* The file path to a server certificate or certificate chain in PEM format.
*
@@ -69,10 +95,23 @@ public class CertificateConfig {
public Optional keyStoreProvider;
/**
- * A parameter to specify the password of the key store file. If not given, the default ("password") is used.
+ * A parameter to specify the password of the key store file. If not given, and if it can not be retrieved from
+ * {@linkplain CredentialsProvider}, then the default ("password") is used.
+ *
+ * @see {@link #credentialsProvider}
*/
- @ConfigItem(defaultValue = "password")
- public String keyStorePassword;
+ @ConfigItem(defaultValueDocumentation = "password")
+ public Optional keyStorePassword;
+
+ /**
+ * A parameter to specify a {@linkplain CredentialsProvider} property key which can be used to get the password of the key
+ * store file
+ * from {@linkplain CredentialsProvider}.
+ *
+ * @see {@link #credentialsProvider}
+ */
+ @ConfigItem
+ public Optional keyStorePasswordKey;
/**
* An optional parameter to select a specific key in the key store. When SNI is disabled, if the key store contains multiple
@@ -82,11 +121,23 @@ public class CertificateConfig {
public Optional keyStoreKeyAlias;
/**
- * An optional parameter to define the password for the key, in case it's different from {@link #keyStorePassword}.
+ * An optional parameter to define the password for the key, in case it's different from {@link #keyStorePassword}
+ * If not given then it may be retrieved from {@linkplain CredentialsProvider}.
+ *
+ * @see {@link #credentialsProvider}.
*/
@ConfigItem
public Optional keyStoreKeyPassword;
+ /**
+ * A parameter to specify a {@linkplain CredentialsProvider} property key which can be used to get the password for the key
+ * from {@linkplain CredentialsProvider}.
+ *
+ * @see {@link #credentialsProvider}
+ */
+ @ConfigItem
+ public Optional keyStoreKeyPasswordKey;
+
/**
* An optional trust store which holds the certificate information of the certificates to trust.
*/
@@ -109,10 +160,23 @@ public class CertificateConfig {
/**
* A parameter to specify the password of the trust store file.
+ * If not given then it may be retrieved from {@linkplain CredentialsProvider}.
+ *
+ * @see {@link #credentialsProvider}.
*/
@ConfigItem
public Optional trustStorePassword;
+ /**
+ * A parameter to specify a {@linkplain CredentialsProvider} property key which can be used to get the password of the trust
+ * store file
+ * from {@linkplain CredentialsProvider}.
+ *
+ * @see {@link #credentialsProvider}
+ */
+ @ConfigItem
+ public Optional trustStorePasswordKey;
+
/**
* An optional parameter to trust only one specific certificate in the trust store (instead of trusting all certificates in
* the store).
diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java
index 557d1391e9a92..00da9c567b72e 100644
--- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java
+++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java
@@ -49,6 +49,8 @@
import io.quarkus.arc.Arc;
import io.quarkus.arc.runtime.BeanContainer;
import io.quarkus.bootstrap.runner.Timing;
+import io.quarkus.credentials.CredentialsProvider;
+import io.quarkus.credentials.runtime.CredentialsProviderFinder;
import io.quarkus.dev.spi.DevModeType;
import io.quarkus.dev.spi.HotReplacementContext;
import io.quarkus.netty.runtime.virtual.VirtualAddress;
@@ -781,10 +783,22 @@ private static HttpServerOptions createSslOptions(HttpBuildTimeConfig buildTimeC
certificates.add(certFile.get());
}
+ // credentials provider
+ Map credentials = Map.of();
+ if (sslConfig.certificate.credentialsProvider.isPresent()) {
+ String beanName = sslConfig.certificate.credentialsProviderName.orElse(null);
+ CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
+ String name = sslConfig.certificate.credentialsProvider.get();
+ credentials = credentialsProvider.getCredentials(name);
+ }
final Optional keyStoreFile = sslConfig.certificate.keyStoreFile;
- final String keystorePassword = sslConfig.certificate.keyStorePassword;
+ final Optional keyStorePassword = getCredential(sslConfig.certificate.keyStorePassword, credentials,
+ sslConfig.certificate.keyStorePasswordKey);
+ final Optional keyStoreKeyPassword = getCredential(sslConfig.certificate.keyStoreKeyPassword, credentials,
+ sslConfig.certificate.keyStoreKeyPasswordKey);
final Optional trustStoreFile = sslConfig.certificate.trustStoreFile;
- final Optional trustStorePassword = sslConfig.certificate.trustStorePassword;
+ final Optional trustStorePassword = getCredential(sslConfig.certificate.trustStorePassword, credentials,
+ sslConfig.certificate.trustStorePasswordKey);
final HttpServerOptions serverOptions = new HttpServerOptions();
//ssl
@@ -801,11 +815,11 @@ private static HttpServerOptions createSslOptions(HttpBuildTimeConfig buildTimeC
} else if (keyStoreFile.isPresent()) {
KeyStoreOptions options = createKeyStoreOptions(
keyStoreFile.get(),
- keystorePassword,
+ keyStorePassword.orElse("password"),
sslConfig.certificate.keyStoreFileType,
sslConfig.certificate.keyStoreProvider,
sslConfig.certificate.keyStoreKeyAlias,
- sslConfig.certificate.keyStoreKeyPassword);
+ keyStoreKeyPassword);
serverOptions.setKeyCertOptions(options);
} else {
return null;
@@ -846,6 +860,19 @@ private static HttpServerOptions createSslOptions(HttpBuildTimeConfig buildTimeC
return serverOptions;
}
+ private static Optional getCredential(Optional password, Map credentials,
+ Optional passwordKey) {
+ if (password.isPresent()) {
+ return password;
+ }
+
+ if (passwordKey.isPresent()) {
+ return Optional.ofNullable(credentials.get(passwordKey.get()));
+ } else {
+ return Optional.empty();
+ }
+ }
+
private static void applyCommonOptions(HttpServerOptions httpServerOptions,
HttpBuildTimeConfig buildTimeConfig,
HttpConfiguration httpConfiguration,
diff --git a/integration-tests/bouncycastle-jsse/src/main/java/io/quarkus/it/bouncycastle/SecretProvider.java b/integration-tests/bouncycastle-jsse/src/main/java/io/quarkus/it/bouncycastle/SecretProvider.java
new file mode 100644
index 0000000000000..9eed67c40298d
--- /dev/null
+++ b/integration-tests/bouncycastle-jsse/src/main/java/io/quarkus/it/bouncycastle/SecretProvider.java
@@ -0,0 +1,23 @@
+package io.quarkus.it.bouncycastle;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import io.quarkus.arc.Unremovable;
+import io.quarkus.credentials.CredentialsProvider;
+
+@ApplicationScoped
+@Unremovable
+public class SecretProvider implements CredentialsProvider {
+
+ @Override
+ public Map getCredentials(String credentialsProviderName) {
+ Map creds = new HashMap<>();
+ creds.put("keystore-password", "password");
+ creds.put("truststore-password", "password");
+ return creds;
+ }
+
+}
diff --git a/integration-tests/bouncycastle-jsse/src/main/resources/application.properties b/integration-tests/bouncycastle-jsse/src/main/resources/application.properties
index 4c0d0e07a2f40..40f0793cd8e70 100644
--- a/integration-tests/bouncycastle-jsse/src/main/resources/application.properties
+++ b/integration-tests/bouncycastle-jsse/src/main/resources/application.properties
@@ -1,9 +1,11 @@
quarkus.security.security-providers=BCJSSE
quarkus.http.ssl.certificate.key-store-file=server-keystore.jks
-quarkus.http.ssl.certificate.key-store-password=password
+quarkus.http.ssl.certificate.key-store-password-key=key-store-password
quarkus.http.ssl.certificate.trust-store-file=server-truststore.jks
-quarkus.http.ssl.certificate.trust-store-password=password
+quarkus.http.ssl.certificate.trust-store-password-key=truststore-password
+quarkus.http.ssl.certificate.credentials-provider=custom
+
quarkus.http.ssl.client-auth=REQUIRED
quarkus.native.additional-build-args=-H:IncludeResources=.*\\.jks