From b4896db2a8276506964fa4d031211f63c97655d5 Mon Sep 17 00:00:00 2001 From: Guillaume Le Floch Date: Tue, 27 Oct 2020 19:57:39 +0100 Subject: [PATCH] Add global quarkus.tls.trust-all configuration property --- .../java/io/quarkus/runtime/TlsConfig.java | 19 +++++++++ .../KeycloakPolicyEnforcerBuildStep.java | 5 ++- .../KeycloakPolicyEnforcerAuthorizer.java | 9 ++++- .../KeycloakPolicyEnforcerRecorder.java | 6 ++- .../deployment/KubernetesClientBuildStep.java | 5 ++- .../runtime/KubernetesClientBuildConfig.java | 2 +- .../runtime/KubernetesClientProducer.java | 5 ++- .../client/runtime/KubernetesClientUtils.java | 10 +++-- .../deployment/KubernetesConfigProcessor.java | 6 ++- .../runtime/KubernetesConfigRecorder.java | 6 ++- .../mailer/runtime/MailClientProducer.java | 14 ++++--- .../io/quarkus/mailer/runtime/MailConfig.java | 4 +- .../mailer/runtime/MutinyMailerImpl.java | 2 +- .../oidc/deployment/OidcBuildStep.java | 6 ++- .../io/quarkus/oidc/OidcTenantConfig.java | 7 ++-- .../io/quarkus/oidc/runtime/OidcRecorder.java | 24 ++++++----- .../restclient/runtime/RestClientBase.java | 40 +++++++++++++------ .../java/io/quarkus/vault/VaultProcessor.java | 6 ++- .../quarkus/vault/runtime/VaultManager.java | 18 ++++++--- .../quarkus/vault/runtime/VaultRecorder.java | 6 ++- .../vault/runtime/VaultServiceProducer.java | 5 ++- .../runtime/client/OkHttpClientFactory.java | 6 ++- .../runtime/client/OkHttpVaultClient.java | 5 ++- .../runtime/config/VaultConfigSource.java | 18 +++++++-- .../runtime/config/VaultRuntimeConfig.java | 1 - .../vault/runtime/config/VaultTlsConfig.java | 5 +-- .../vault/runtime/VaultAuthManagerTest.java | 6 ++- .../vault/runtime/VaultDbManagerTest.java | 6 ++- .../trustall/ExternalTlsTrustAllIT.java | 7 ++++ .../trustall/ExternalTlsTrustAllTestCase.java | 23 +++++++++++ .../ExternalTlsTrustAllTestResource.java | 23 +++++++++++ .../application-vault-multi-path.properties | 2 +- .../vault/test/VaultTestExtension.java | 6 ++- .../vault/test/client/TestVaultClient.java | 7 ++-- 34 files changed, 232 insertions(+), 88 deletions(-) create mode 100644 core/runtime/src/main/java/io/quarkus/runtime/TlsConfig.java create mode 100644 integration-tests/rest-client/src/test/java/io/quarkus/it/rest/client/trustall/ExternalTlsTrustAllIT.java create mode 100644 integration-tests/rest-client/src/test/java/io/quarkus/it/rest/client/trustall/ExternalTlsTrustAllTestCase.java create mode 100644 integration-tests/rest-client/src/test/java/io/quarkus/it/rest/client/trustall/ExternalTlsTrustAllTestResource.java diff --git a/core/runtime/src/main/java/io/quarkus/runtime/TlsConfig.java b/core/runtime/src/main/java/io/quarkus/runtime/TlsConfig.java new file mode 100644 index 0000000000000..9b4409fb540e9 --- /dev/null +++ b/core/runtime/src/main/java/io/quarkus/runtime/TlsConfig.java @@ -0,0 +1,19 @@ +package io.quarkus.runtime; + +import io.quarkus.runtime.annotations.ConfigItem; +import io.quarkus.runtime.annotations.ConfigPhase; +import io.quarkus.runtime.annotations.ConfigRoot; + +/** + * Configuration class allowing to globally set TLS properties. + */ +@ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) +public class TlsConfig { + + /** + * Enable trusting all certificates. Disable by default. + */ + @ConfigItem(defaultValue = "false") + public boolean trustAll; + +} \ No newline at end of file diff --git a/extensions/keycloak-authorization/deployment/src/main/java/io/quarkus/keycloak/pep/deployment/KeycloakPolicyEnforcerBuildStep.java b/extensions/keycloak-authorization/deployment/src/main/java/io/quarkus/keycloak/pep/deployment/KeycloakPolicyEnforcerBuildStep.java index d28864b8e5448..c1fe6d1d1e849 100644 --- a/extensions/keycloak-authorization/deployment/src/main/java/io/quarkus/keycloak/pep/deployment/KeycloakPolicyEnforcerBuildStep.java +++ b/extensions/keycloak-authorization/deployment/src/main/java/io/quarkus/keycloak/pep/deployment/KeycloakPolicyEnforcerBuildStep.java @@ -15,6 +15,7 @@ import io.quarkus.keycloak.pep.runtime.KeycloakPolicyEnforcerRecorder; import io.quarkus.oidc.runtime.OidcBuildTimeConfig; import io.quarkus.oidc.runtime.OidcConfig; +import io.quarkus.runtime.TlsConfig; import io.quarkus.vertx.http.deployment.RequireBodyHandlerBuildItem; import io.quarkus.vertx.http.runtime.HttpConfiguration; @@ -71,11 +72,11 @@ EnableAllSecurityServicesBuildItem security() { @Record(ExecutionTime.RUNTIME_INIT) @BuildStep - public void setup(OidcBuildTimeConfig oidcBuildTimeConfig, OidcConfig oidcRunTimeConfig, + public void setup(OidcBuildTimeConfig oidcBuildTimeConfig, OidcConfig oidcRunTimeConfig, TlsConfig tlsConfig, KeycloakPolicyEnforcerConfig keycloakConfig, KeycloakPolicyEnforcerRecorder recorder, BeanContainerBuildItem bc, HttpConfiguration httpConfiguration) { if (oidcBuildTimeConfig.enabled && keycloakConfig.policyEnforcer.enable) { - recorder.setup(oidcRunTimeConfig, keycloakConfig, bc.getValue(), httpConfiguration); + recorder.setup(oidcRunTimeConfig, keycloakConfig, tlsConfig, bc.getValue(), httpConfiguration); } } } diff --git a/extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/KeycloakPolicyEnforcerAuthorizer.java b/extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/KeycloakPolicyEnforcerAuthorizer.java index 8083f1d61e10c..f6dda5b3c6b72 100644 --- a/extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/KeycloakPolicyEnforcerAuthorizer.java +++ b/extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/KeycloakPolicyEnforcerAuthorizer.java @@ -20,6 +20,7 @@ import io.quarkus.oidc.OidcTenantConfig; import io.quarkus.oidc.OidcTenantConfig.Tls.Verification; import io.quarkus.oidc.runtime.OidcConfig; +import io.quarkus.runtime.TlsConfig; import io.quarkus.security.identity.SecurityIdentity; import io.quarkus.security.runtime.QuarkusSecurityIdentity; import io.quarkus.vertx.http.runtime.HttpConfiguration; @@ -90,7 +91,8 @@ public Uni apply(Permission permission) { }).build(); } - public void init(OidcConfig oidcConfig, KeycloakPolicyEnforcerConfig config, HttpConfiguration httpConfiguration) { + public void init(OidcConfig oidcConfig, KeycloakPolicyEnforcerConfig config, TlsConfig tlsConfig, + HttpConfiguration httpConfiguration) { AdapterConfig adapterConfig = new AdapterConfig(); String authServerUrl = oidcConfig.defaultTenant.getAuthServerUrl().get(); @@ -104,7 +106,10 @@ public void init(OidcConfig oidcConfig, KeycloakPolicyEnforcerConfig config, Htt adapterConfig.setResource(oidcConfig.defaultTenant.getClientId().get()); adapterConfig.setCredentials(getCredentials(oidcConfig.defaultTenant)); - if (oidcConfig.defaultTenant.tls.getVerification() == Verification.NONE) { + boolean trustAll = oidcConfig.defaultTenant.tls.getVerification().isPresent() + ? oidcConfig.defaultTenant.tls.getVerification().get() == Verification.NONE + : tlsConfig.trustAll; + if (trustAll) { adapterConfig.setDisableTrustManager(true); adapterConfig.setAllowAnyHostname(true); } diff --git a/extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/KeycloakPolicyEnforcerRecorder.java b/extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/KeycloakPolicyEnforcerRecorder.java index 13481c193a622..23037ec5bc072 100644 --- a/extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/KeycloakPolicyEnforcerRecorder.java +++ b/extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/KeycloakPolicyEnforcerRecorder.java @@ -4,17 +4,19 @@ import io.quarkus.oidc.OIDCException; import io.quarkus.oidc.OidcTenantConfig; import io.quarkus.oidc.runtime.OidcConfig; +import io.quarkus.runtime.TlsConfig; import io.quarkus.runtime.annotations.Recorder; import io.quarkus.vertx.http.runtime.HttpConfiguration; @Recorder public class KeycloakPolicyEnforcerRecorder { - public void setup(OidcConfig oidcConfig, KeycloakPolicyEnforcerConfig config, BeanContainer beanContainer, + public void setup(OidcConfig oidcConfig, KeycloakPolicyEnforcerConfig config, TlsConfig tlsConfig, + BeanContainer beanContainer, HttpConfiguration httpConfiguration) { if (oidcConfig.defaultTenant.applicationType == OidcTenantConfig.ApplicationType.WEB_APP) { throw new OIDCException("Application type [" + oidcConfig.defaultTenant.applicationType + "] is not supported"); } - beanContainer.instance(KeycloakPolicyEnforcerAuthorizer.class).init(oidcConfig, config, httpConfiguration); + beanContainer.instance(KeycloakPolicyEnforcerAuthorizer.class).init(oidcConfig, config, tlsConfig, httpConfiguration); } } diff --git a/extensions/kubernetes-client/deployment-internal/src/main/java/io/quarkus/kubernetes/client/deployment/KubernetesClientBuildStep.java b/extensions/kubernetes-client/deployment-internal/src/main/java/io/quarkus/kubernetes/client/deployment/KubernetesClientBuildStep.java index 202cbab8a0480..a65b82da207ae 100644 --- a/extensions/kubernetes-client/deployment-internal/src/main/java/io/quarkus/kubernetes/client/deployment/KubernetesClientBuildStep.java +++ b/extensions/kubernetes-client/deployment-internal/src/main/java/io/quarkus/kubernetes/client/deployment/KubernetesClientBuildStep.java @@ -5,13 +5,14 @@ import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.kubernetes.client.runtime.KubernetesClientBuildConfig; import io.quarkus.kubernetes.client.spi.KubernetesClientBuildItem; +import io.quarkus.runtime.TlsConfig; public class KubernetesClientBuildStep { private KubernetesClientBuildConfig buildConfig; @BuildStep - public KubernetesClientBuildItem process() { - return new KubernetesClientBuildItem(createClient(buildConfig)); + public KubernetesClientBuildItem process(TlsConfig tlsConfig) { + return new KubernetesClientBuildItem(createClient(buildConfig, tlsConfig)); } } diff --git a/extensions/kubernetes-client/runtime-internal/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientBuildConfig.java b/extensions/kubernetes-client/runtime-internal/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientBuildConfig.java index 7a27f645a0782..a8f6c41fe780b 100644 --- a/extensions/kubernetes-client/runtime-internal/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientBuildConfig.java +++ b/extensions/kubernetes-client/runtime-internal/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientBuildConfig.java @@ -14,7 +14,7 @@ public class KubernetesClientBuildConfig { * Whether or not the client should trust a self signed certificate if so presented by the API server */ @ConfigItem - public boolean trustCerts; + public Optional trustCerts = Optional.empty(); /** * URL of the Kubernetes API server diff --git a/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientProducer.java b/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientProducer.java index 0e3eb8fed6981..d4129a4c561cc 100644 --- a/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientProducer.java +++ b/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientProducer.java @@ -8,6 +8,7 @@ import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; import io.quarkus.arc.DefaultBean; +import io.quarkus.runtime.TlsConfig; @Singleton public class KubernetesClientProducer { @@ -17,8 +18,8 @@ public class KubernetesClientProducer { @DefaultBean @Singleton @Produces - public Config config(KubernetesClientBuildConfig buildConfig) { - return KubernetesClientUtils.createConfig(buildConfig); + public Config config(KubernetesClientBuildConfig buildConfig, TlsConfig tlsConfig) { + return KubernetesClientUtils.createConfig(buildConfig, tlsConfig); } @DefaultBean diff --git a/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientUtils.java b/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientUtils.java index 1429c17453a44..ed908c62b17f6 100644 --- a/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientUtils.java +++ b/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientUtils.java @@ -8,15 +8,17 @@ import io.fabric8.kubernetes.client.ConfigBuilder; import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; +import io.quarkus.runtime.TlsConfig; public class KubernetesClientUtils { private static final String PREFIX = "quarkus.kubernetes-client."; - public static Config createConfig(KubernetesClientBuildConfig buildConfig) { + public static Config createConfig(KubernetesClientBuildConfig buildConfig, TlsConfig tlsConfig) { Config base = Config.autoConfigure(null); + boolean trustAll = buildConfig.trustCerts.isPresent() ? buildConfig.trustCerts.get() : tlsConfig.trustAll; return new ConfigBuilder() - .withTrustCerts(buildConfig.trustCerts) + .withTrustCerts(trustAll) .withWatchReconnectInterval((int) buildConfig.watchReconnectInterval.toMillis()) .withWatchReconnectLimit(buildConfig.watchReconnectLimit) .withConnectionTimeout((int) buildConfig.connectionTimeout.toMillis()) @@ -43,8 +45,8 @@ public static Config createConfig(KubernetesClientBuildConfig buildConfig) { .build(); } - public static KubernetesClient createClient(KubernetesClientBuildConfig buildConfig) { - return new DefaultKubernetesClient(createConfig(buildConfig)); + public static KubernetesClient createClient(KubernetesClientBuildConfig buildConfig, TlsConfig tlsConfig) { + return new DefaultKubernetesClient(createConfig(buildConfig, tlsConfig)); } public static KubernetesClient createClient() { diff --git a/extensions/kubernetes-config/deployment/src/main/java/io/quarkus/kubernetes/config/deployment/KubernetesConfigProcessor.java b/extensions/kubernetes-config/deployment/src/main/java/io/quarkus/kubernetes/config/deployment/KubernetesConfigProcessor.java index c08aae468ce95..b2703311dab70 100644 --- a/extensions/kubernetes-config/deployment/src/main/java/io/quarkus/kubernetes/config/deployment/KubernetesConfigProcessor.java +++ b/extensions/kubernetes-config/deployment/src/main/java/io/quarkus/kubernetes/config/deployment/KubernetesConfigProcessor.java @@ -17,6 +17,7 @@ import io.quarkus.kubernetes.client.runtime.KubernetesConfigSourceConfig; import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem; +import io.quarkus.runtime.TlsConfig; public class KubernetesConfigProcessor { @@ -24,9 +25,10 @@ public class KubernetesConfigProcessor { @Record(ExecutionTime.RUNTIME_INIT) public RunTimeConfigurationSourceValueBuildItem configure(KubernetesConfigRecorder recorder, KubernetesConfigSourceConfig config, KubernetesConfigBuildTimeConfig buildTimeConfig, - KubernetesClientBuildConfig clientConfig) { + KubernetesClientBuildConfig clientConfig, + TlsConfig tlsConfig) { return new RunTimeConfigurationSourceValueBuildItem( - recorder.configSources(config, buildTimeConfig, clientConfig)); + recorder.configSources(config, buildTimeConfig, clientConfig, tlsConfig)); } @BuildStep diff --git a/extensions/kubernetes-config/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesConfigRecorder.java b/extensions/kubernetes-config/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesConfigRecorder.java index 0e4aa5bd011e2..37aed2a4f786e 100644 --- a/extensions/kubernetes-config/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesConfigRecorder.java +++ b/extensions/kubernetes-config/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesConfigRecorder.java @@ -9,6 +9,7 @@ import org.jboss.logging.Logger; import io.quarkus.runtime.RuntimeValue; +import io.quarkus.runtime.TlsConfig; import io.quarkus.runtime.annotations.Recorder; import io.quarkus.runtime.configuration.AbstractRawDefaultConfigSource; @@ -21,7 +22,8 @@ public class KubernetesConfigRecorder { public RuntimeValue configSources(KubernetesConfigSourceConfig kubernetesConfigSourceConfig, KubernetesConfigBuildTimeConfig buildTimeConfig, - KubernetesClientBuildConfig clientConfig) { + KubernetesClientBuildConfig clientConfig, + TlsConfig tlsConfig) { if ((!kubernetesConfigSourceConfig.enabled && !buildTimeConfig.secretsEnabled) || isExplicitlyDisabled()) { log.debug( "No attempt will be made to obtain configuration from the Kubernetes API server because the functionality has been disabled via configuration"); @@ -29,7 +31,7 @@ public RuntimeValue configSources(KubernetesConfigSourceCo } return new RuntimeValue<>(new KubernetesConfigSourceProvider(kubernetesConfigSourceConfig, buildTimeConfig, - KubernetesClientUtils.createClient(clientConfig))); + KubernetesClientUtils.createClient(clientConfig, tlsConfig))); } // We don't want to enable the reading of anything if 'quarkus.kubernetes-config.enabled' is EXPLICITLY set to false diff --git a/extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MailClientProducer.java b/extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MailClientProducer.java index c588e8fd00590..355ae161296dd 100644 --- a/extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MailClientProducer.java +++ b/extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MailClientProducer.java @@ -7,6 +7,7 @@ import org.jboss.logging.Logger; +import io.quarkus.runtime.TlsConfig; import io.vertx.core.Vertx; import io.vertx.ext.mail.LoginOption; import io.vertx.ext.mail.MailClient; @@ -23,8 +24,8 @@ public class MailClientProducer { private final io.vertx.mutiny.ext.mail.MailClient mutinyClient; private final MailClient client; - public MailClientProducer(Vertx vertx, MailConfig config) { - this.client = mailClient(vertx, config); + public MailClientProducer(Vertx vertx, MailConfig config, TlsConfig tlsConfig) { + this.client = mailClient(vertx, config, tlsConfig); this.mutinyClient = io.vertx.mutiny.ext.mail.MailClient.newInstance(this.client); } @@ -65,12 +66,12 @@ public void stop() { client.close(); } - private MailClient mailClient(Vertx vertx, MailConfig config) { - io.vertx.ext.mail.MailConfig cfg = toVertxMailConfig(config); + private MailClient mailClient(Vertx vertx, MailConfig config, TlsConfig tlsConfig) { + io.vertx.ext.mail.MailConfig cfg = toVertxMailConfig(config, tlsConfig); return MailClient.createShared(vertx, cfg); } - private io.vertx.ext.mail.MailConfig toVertxMailConfig(MailConfig config) { + private io.vertx.ext.mail.MailConfig toVertxMailConfig(MailConfig config, TlsConfig tlsConfig) { io.vertx.ext.mail.MailConfig cfg = new io.vertx.ext.mail.MailConfig(); if (config.authMethods.isPresent()) { cfg.setAuthMethods(config.authMethods.get()); @@ -106,7 +107,8 @@ private io.vertx.ext.mail.MailConfig toVertxMailConfig(MailConfig config) { if (config.startTLS.isPresent()) { cfg.setStarttls(StartTLSOptions.valueOf(config.startTLS.get().toUpperCase())); } - cfg.setTrustAll(config.trustAll); + boolean trustAll = config.trustAll.isPresent() ? config.trustAll.get() : tlsConfig.trustAll; + cfg.setTrustAll(trustAll); return cfg; } diff --git a/extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MailConfig.java b/extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MailConfig.java index 6a12c598d04d3..d4d31b434518a 100644 --- a/extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MailConfig.java +++ b/extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MailConfig.java @@ -65,10 +65,10 @@ public class MailConfig { /** * Set whether to trust all certificates on ssl connect the option is also - * applied to {@code STARTTLS} operation. {@code false} by default. + * applied to {@code STARTTLS} operation. Disabled by default. */ @ConfigItem - public boolean trustAll; + public Optional trustAll = Optional.empty(); /** * Configures the maximum allowed number of open connections to the mail server diff --git a/extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MutinyMailerImpl.java b/extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MutinyMailerImpl.java index 213a1594c7073..38aeb241638a1 100644 --- a/extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MutinyMailerImpl.java +++ b/extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MutinyMailerImpl.java @@ -51,7 +51,7 @@ public class MutinyMailerImpl implements ReactiveMailer { public Void apply(List results) { return null; } - };; + }; @Override public Uni send(Mail... mails) { diff --git a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java index d0f930b354d8f..fe7ba790e86cc 100644 --- a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java +++ b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java @@ -35,6 +35,7 @@ import io.quarkus.oidc.runtime.OidcRecorder; import io.quarkus.oidc.runtime.OidcTokenCredentialProducer; import io.quarkus.oidc.runtime.TenantConfigBean; +import io.quarkus.runtime.TlsConfig; import io.quarkus.vertx.core.deployment.CoreVertxBuildItem; import io.smallrye.jwt.auth.cdi.ClaimValueProducer; import io.smallrye.jwt.auth.cdi.CommonJwtProducer; @@ -92,9 +93,10 @@ EnableAllSecurityServicesBuildItem security() { public SyntheticBeanBuildItem setup( OidcConfig config, OidcRecorder recorder, - CoreVertxBuildItem vertxBuildItem) { + CoreVertxBuildItem vertxBuildItem, + TlsConfig tlsConfig) { return SyntheticBeanBuildItem.configure(TenantConfigBean.class).unremovable().types(TenantConfigBean.class) - .supplier(recorder.setup(config, vertxBuildItem.getVertx())) + .supplier(recorder.setup(config, vertxBuildItem.getVertx(), tlsConfig)) .scope(Singleton.class) .setRuntimeInit() .done(); diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcTenantConfig.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcTenantConfig.java index fec49f5bdf193..28f0c4ea84ebe 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcTenantConfig.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcTenantConfig.java @@ -187,15 +187,14 @@ public enum Verification { * Certificate validation and hostname verification, which can be one of the following values from enum * {@link Verification}. Default is required. */ - @ConfigItem(defaultValue = "REQUIRED") - public Verification verification; + public Optional verification = Optional.empty(); - public Verification getVerification() { + public Optional getVerification() { return verification; } public void setVerification(Verification verification) { - this.verification = verification; + this.verification = Optional.ofNullable(verification); } } diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcRecorder.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcRecorder.java index 23c4c2c6a5641..baf33c8ee6819 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcRecorder.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcRecorder.java @@ -21,6 +21,7 @@ import io.quarkus.oidc.OidcTenantConfig.Tls.Verification; import io.quarkus.runtime.BlockingOperationControl; import io.quarkus.runtime.ExecutorRecorder; +import io.quarkus.runtime.TlsConfig; import io.quarkus.runtime.annotations.Recorder; import io.quarkus.runtime.configuration.ConfigurationException; import io.smallrye.mutiny.Uni; @@ -44,7 +45,7 @@ public class OidcRecorder { private static final Map dynamicTenantsConfig = new ConcurrentHashMap<>(); - public Supplier setup(OidcConfig config, Supplier vertx) { + public Supplier setup(OidcConfig config, Supplier vertx, TlsConfig tlsConfig) { final Vertx vertxValue = vertx.get(); Map staticTenantsConfig = new HashMap<>(); @@ -57,10 +58,12 @@ public Supplier setup(OidcConfig config, Supplier vertx throw new OIDCException("Configuration has 2 different tenant-id values: '" + tenant.getKey() + "' and '" + tenant.getValue().getTenantId().get() + "'"); } - staticTenantsConfig.put(tenant.getKey(), createTenantContext(vertxValue, tenant.getValue(), tenant.getKey())); + staticTenantsConfig.put(tenant.getKey(), + createTenantContext(vertxValue, tenant.getValue(), tlsConfig, tenant.getKey())); } - TenantConfigContext tenantContext = createTenantContext(vertxValue, config.defaultTenant, "Default"); + TenantConfigContext tenantContext = createTenantContext(vertxValue, config.defaultTenant, tlsConfig, "Default"); + return new Supplier() { @Override public TenantConfigBean get() { @@ -73,13 +76,13 @@ public Uni apply(OidcTenantConfig config) { @Override public void accept(UniEmitter uniEmitter) { if (BlockingOperationControl.isBlockingAllowed()) { - createDynamicTenantContext(uniEmitter, vertxValue, config, + createDynamicTenantContext(uniEmitter, vertxValue, config, tlsConfig, config.getTenantId().get()); } else { ExecutorRecorder.getCurrent().execute(new Runnable() { @Override public void run() { - createDynamicTenantContext(uniEmitter, vertxValue, config, + createDynamicTenantContext(uniEmitter, vertxValue, config, tlsConfig, config.getTenantId().get()); } }); @@ -95,10 +98,10 @@ public void run() { } private void createDynamicTenantContext(UniEmitter uniEmitter, Vertx vertx, - OidcTenantConfig oidcConfig, String tenantId) { + OidcTenantConfig oidcConfig, TlsConfig tlsConfig, String tenantId) { try { if (!dynamicTenantsConfig.containsKey(tenantId)) { - dynamicTenantsConfig.putIfAbsent(tenantId, createTenantContext(vertx, oidcConfig, tenantId)); + dynamicTenantsConfig.putIfAbsent(tenantId, createTenantContext(vertx, oidcConfig, tlsConfig, tenantId)); } uniEmitter.complete(dynamicTenantsConfig.get(tenantId)); } catch (Throwable t) { @@ -106,7 +109,8 @@ private void createDynamicTenantContext(UniEmitter } } - private TenantConfigContext createTenantContext(Vertx vertx, OidcTenantConfig oidcConfig, String tenantId) { + private TenantConfigContext createTenantContext(Vertx vertx, OidcTenantConfig oidcConfig, TlsConfig tlsConfig, + String tenantId) { if (!oidcConfig.tenantId.isPresent()) { oidcConfig.tenantId = Optional.of(tenantId); } @@ -234,7 +238,9 @@ private TenantConfigContext createTenantContext(Vertx vertx, OidcTenantConfig oi options.setProxyOptions(proxyOpt.get()); } - if (oidcConfig.tls.verification == Verification.NONE) { + boolean trustAll = oidcConfig.tls.verification.isPresent() ? oidcConfig.tls.verification.get() == Verification.NONE + : tlsConfig.trustAll; + if (trustAll) { options.setTrustAll(true); options.setVerifyHost(false); } diff --git a/extensions/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientBase.java b/extensions/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientBase.java index 9d402bb45f1e1..c44691cab8316 100644 --- a/extensions/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientBase.java +++ b/extensions/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientBase.java @@ -44,6 +44,8 @@ public class RestClientBase { public static final String REST_KEY_STORE_PASSWORD = "%s/" + MP_REST + "/keyStorePassword"; public static final String REST_KEY_STORE_TYPE = "%s/" + MP_REST + "/keyStoreType"; public static final String REST_HOSTNAME_VERIFIER = "%s/" + MP_REST + "/hostnameVerifier"; + public static final String REST_NOOP_HOSTNAME_VERIFIER = "io.quarkus.restclient.NoopHostnameVerifier"; + public static final String TLS_TRUST_ALL = "quarkus.tls.trust-all"; private final Class proxyType; private final String baseUriFromAnnotation; @@ -72,17 +74,23 @@ public Object create() { } private void configureSsl(RestClientBuilder builder) { - Optional maybeTrustStore = getOptionalProperty(REST_TRUST_STORE, String.class); + + Optional trustAll = getOptionalProperty(TLS_TRUST_ALL, Boolean.class); + if (trustAll.isPresent() && trustAll.get()) { + registerHostnameVerifier(REST_NOOP_HOSTNAME_VERIFIER, builder); + } + + Optional maybeTrustStore = getOptionalDynamicProperty(REST_TRUST_STORE, String.class); if (maybeTrustStore.isPresent()) { registerTrustStore(maybeTrustStore.get(), builder); } - Optional maybeKeyStore = getOptionalProperty(REST_KEY_STORE, String.class); + Optional maybeKeyStore = getOptionalDynamicProperty(REST_KEY_STORE, String.class); if (maybeKeyStore.isPresent()) { registerKeyStore(maybeKeyStore.get(), builder); } - Optional maybeHostnameVerifier = getOptionalProperty(REST_HOSTNAME_VERIFIER, String.class); + Optional maybeHostnameVerifier = getOptionalDynamicProperty(REST_HOSTNAME_VERIFIER, String.class); if (maybeHostnameVerifier.isPresent()) { registerHostnameVerifier(maybeHostnameVerifier.get(), builder); } @@ -115,8 +123,8 @@ private void registerHostnameVerifier(String verifier, RestClientBuilder builder } private void registerKeyStore(String keyStorePath, RestClientBuilder builder) { - Optional keyStorePassword = getOptionalProperty(REST_KEY_STORE_PASSWORD, String.class); - Optional keyStoreType = getOptionalProperty(REST_KEY_STORE_TYPE, String.class); + Optional keyStorePassword = getOptionalDynamicProperty(REST_KEY_STORE_PASSWORD, String.class); + Optional keyStoreType = getOptionalDynamicProperty(REST_KEY_STORE_TYPE, String.class); try { KeyStore keyStore = KeyStore.getInstance(keyStoreType.orElse("JKS")); @@ -139,8 +147,8 @@ private void registerKeyStore(String keyStorePath, RestClientBuilder builder) { } private void registerTrustStore(String trustStorePath, RestClientBuilder builder) { - Optional maybeTrustStorePassword = getOptionalProperty(REST_TRUST_STORE_PASSWORD, String.class); - Optional maybeTrustStoreType = getOptionalProperty(REST_TRUST_STORE_TYPE, String.class); + Optional maybeTrustStorePassword = getOptionalDynamicProperty(REST_TRUST_STORE_PASSWORD, String.class); + Optional maybeTrustStoreType = getOptionalDynamicProperty(REST_TRUST_STORE_TYPE, String.class); try { KeyStore trustStore = KeyStore.getInstance(maybeTrustStoreType.orElse("JKS")); @@ -188,7 +196,7 @@ private InputStream locateStream(String path) throws FileNotFoundException { } private void configureProviders(RestClientBuilder builder) { - Optional maybeProviders = getOptionalProperty(REST_PROVIDERS, String.class); + Optional maybeProviders = getOptionalDynamicProperty(REST_PROVIDERS, String.class); if (maybeProviders.isPresent()) { registerProviders(builder, maybeProviders.get()); } @@ -209,21 +217,21 @@ private Class providerClassForName(String name) { } private void configureTimeouts(RestClientBuilder builder) { - Optional connectTimeout = getOptionalProperty(REST_CONNECT_TIMEOUT_FORMAT, Long.class); + Optional connectTimeout = getOptionalDynamicProperty(REST_CONNECT_TIMEOUT_FORMAT, Long.class); if (connectTimeout.isPresent()) { builder.connectTimeout(connectTimeout.get(), TimeUnit.MILLISECONDS); } - Optional readTimeout = getOptionalProperty(REST_READ_TIMEOUT_FORMAT, Long.class); + Optional readTimeout = getOptionalDynamicProperty(REST_READ_TIMEOUT_FORMAT, Long.class); if (readTimeout.isPresent()) { builder.readTimeout(readTimeout.get(), TimeUnit.MILLISECONDS); } } private void configureBaseUrl(RestClientBuilder builder) { - Optional propertyOptional = getOptionalProperty(REST_URI_FORMAT, String.class); + Optional propertyOptional = getOptionalDynamicProperty(REST_URI_FORMAT, String.class); if (!propertyOptional.isPresent()) { - propertyOptional = getOptionalProperty(REST_URL_FORMAT, String.class); + propertyOptional = getOptionalDynamicProperty(REST_URL_FORMAT, String.class); } if (((baseUriFromAnnotation == null) || baseUriFromAnnotation.isEmpty()) && !propertyOptional.isPresent()) { @@ -250,10 +258,16 @@ private void configureBaseUrl(RestClientBuilder builder) { } } - private Optional getOptionalProperty(String propertyFormat, Class type) { + private Optional getOptionalDynamicProperty(String propertyFormat, Class type) { final Config config = ConfigProvider.getConfig(); Optional interfaceNameValue = config.getOptionalValue(String.format(propertyFormat, proxyType.getName()), type); return interfaceNameValue.isPresent() ? interfaceNameValue : config.getOptionalValue(String.format(propertyFormat, propertyPrefix), type); } + + private Optional getOptionalProperty(String propertyName, Class type) { + final Config config = ConfigProvider.getConfig(); + return config.getOptionalValue(propertyName, type); + } + } diff --git a/extensions/vault/deployment/src/main/java/io/quarkus/vault/VaultProcessor.java b/extensions/vault/deployment/src/main/java/io/quarkus/vault/VaultProcessor.java index cf21623dd2f5b..28d88c86b16aa 100644 --- a/extensions/vault/deployment/src/main/java/io/quarkus/vault/VaultProcessor.java +++ b/extensions/vault/deployment/src/main/java/io/quarkus/vault/VaultProcessor.java @@ -17,6 +17,7 @@ import io.quarkus.deployment.builditem.RunTimeConfigurationSourceBuildItem; import io.quarkus.deployment.builditem.SslNativeConfigBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; +import io.quarkus.runtime.TlsConfig; import io.quarkus.smallrye.health.deployment.spi.HealthBuildItem; import io.quarkus.vault.runtime.Base64StringDeserializer; import io.quarkus.vault.runtime.Base64StringSerializer; @@ -73,8 +74,9 @@ AdditionalBeanBuildItem registerAdditionalBeans() { @Record(ExecutionTime.RUNTIME_INIT) @BuildStep - void configure(VaultRecorder recorder, VaultBuildTimeConfig buildTimeConfig, VaultRuntimeConfig serverConfig) { - recorder.configureRuntimeProperties(buildTimeConfig, serverConfig); + void configure(VaultRecorder recorder, VaultBuildTimeConfig buildTimeConfig, VaultRuntimeConfig serverConfig, + TlsConfig tlsConfig) { + recorder.configureRuntimeProperties(buildTimeConfig, serverConfig, tlsConfig); } @BuildStep diff --git a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/VaultManager.java b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/VaultManager.java index 1e16877d988bd..c2db3bd676873 100644 --- a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/VaultManager.java +++ b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/VaultManager.java @@ -1,5 +1,6 @@ package io.quarkus.vault.runtime; +import io.quarkus.runtime.TlsConfig; import io.quarkus.vault.runtime.client.OkHttpVaultClient; import io.quarkus.vault.runtime.client.VaultClient; import io.quarkus.vault.runtime.config.VaultBuildTimeConfig; @@ -11,6 +12,7 @@ public class VaultManager { private VaultRuntimeConfig serverConfig; private VaultBuildTimeConfig buildTimeConfig; + private TlsConfig tlsConfig; private VaultClient vaultClient; private VaultAuthManager vaultAuthManager; @@ -26,9 +28,9 @@ public static VaultManager getInstance() { return instance; } - public static void init(VaultBuildTimeConfig buildTimeConfig, VaultRuntimeConfig serverConfig) { + public static void init(VaultBuildTimeConfig buildTimeConfig, VaultRuntimeConfig serverConfig, TlsConfig tlsConfig) { if (instance == null) { - instance = new VaultManager(buildTimeConfig, serverConfig); + instance = new VaultManager(buildTimeConfig, serverConfig, tlsConfig); } } @@ -36,14 +38,16 @@ public static void reset() { instance = null; } - public VaultManager(VaultBuildTimeConfig vaultBuildTimeConfig, VaultRuntimeConfig serverConfig) { - this(vaultBuildTimeConfig, serverConfig, new OkHttpVaultClient(serverConfig)); + public VaultManager(VaultBuildTimeConfig vaultBuildTimeConfig, VaultRuntimeConfig serverConfig, TlsConfig tlsConfig) { + this(vaultBuildTimeConfig, serverConfig, new OkHttpVaultClient(serverConfig, tlsConfig), tlsConfig); } - public VaultManager(VaultBuildTimeConfig vaultBuildTimeConfig, VaultRuntimeConfig serverConfig, VaultClient vaultClient) { + public VaultManager(VaultBuildTimeConfig vaultBuildTimeConfig, VaultRuntimeConfig serverConfig, VaultClient vaultClient, + TlsConfig tlsConfig) { this.serverConfig = serverConfig; this.vaultClient = vaultClient; this.buildTimeConfig = vaultBuildTimeConfig; + this.tlsConfig = tlsConfig; this.vaultAuthManager = new VaultAuthManager(this.vaultClient, serverConfig); this.vaultKvManager = new VaultKvManager(this.vaultAuthManager, this.vaultClient, serverConfig); this.vaultDbManager = new VaultDbManager(this.vaultAuthManager, this.vaultClient, serverConfig); @@ -91,6 +95,10 @@ public VaultBuildTimeConfig getBuildTimeConfig() { return buildTimeConfig; } + public TlsConfig getTlsConfig() { + return tlsConfig; + } + public VaultSystemBackendManager getVaultSystemBackendManager() { return vaultSystemBackendManager; } diff --git a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/VaultRecorder.java b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/VaultRecorder.java index 1578de99956f7..bc25e869776a2 100644 --- a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/VaultRecorder.java +++ b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/VaultRecorder.java @@ -3,6 +3,7 @@ import org.jboss.logging.Logger; import io.quarkus.arc.Arc; +import io.quarkus.runtime.TlsConfig; import io.quarkus.runtime.annotations.Recorder; import io.quarkus.vault.runtime.config.VaultBuildTimeConfig; import io.quarkus.vault.runtime.config.VaultRuntimeConfig; @@ -12,11 +13,12 @@ public class VaultRecorder { private static final Logger log = Logger.getLogger(VaultRecorder.class); - public void configureRuntimeProperties(VaultBuildTimeConfig vaultBuildTimeConfig, VaultRuntimeConfig vaultRuntimeConfig) { + public void configureRuntimeProperties(VaultBuildTimeConfig vaultBuildTimeConfig, VaultRuntimeConfig vaultRuntimeConfig, + TlsConfig tlsConfig) { if (vaultRuntimeConfig.url.isPresent()) { VaultServiceProducer producer = Arc.container().instance(VaultServiceProducer.class).get(); - producer.setVaultConfigs(vaultBuildTimeConfig, vaultRuntimeConfig); + producer.setVaultConfigs(vaultBuildTimeConfig, vaultRuntimeConfig, tlsConfig); } } diff --git a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/VaultServiceProducer.java b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/VaultServiceProducer.java index 06e4c5a40ed1a..0c98c37bd6718 100644 --- a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/VaultServiceProducer.java +++ b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/VaultServiceProducer.java @@ -6,6 +6,7 @@ import javax.inject.Named; import io.quarkus.credentials.CredentialsProvider; +import io.quarkus.runtime.TlsConfig; import io.quarkus.vault.VaultKVSecretEngine; import io.quarkus.vault.VaultSystemBackendEngine; import io.quarkus.vault.VaultTOTPSecretEngine; @@ -58,7 +59,7 @@ public void close() { VaultManager.reset(); } - public void setVaultConfigs(VaultBuildTimeConfig buildTimeConfig, VaultRuntimeConfig serverConfig) { - VaultManager.init(buildTimeConfig, serverConfig); + public void setVaultConfigs(VaultBuildTimeConfig buildTimeConfig, VaultRuntimeConfig serverConfig, TlsConfig tlsConfig) { + VaultManager.init(buildTimeConfig, serverConfig, tlsConfig); } } diff --git a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/client/OkHttpClientFactory.java b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/client/OkHttpClientFactory.java index b1f9a896ffb6c..55bc63b596282 100644 --- a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/client/OkHttpClientFactory.java +++ b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/client/OkHttpClientFactory.java @@ -17,6 +17,7 @@ import org.jboss.logging.Logger; +import io.quarkus.runtime.TlsConfig; import io.quarkus.runtime.util.JavaVersionUtil; import io.quarkus.vault.VaultException; import io.quarkus.vault.runtime.config.VaultRuntimeConfig; @@ -27,7 +28,7 @@ public class OkHttpClientFactory { private static final Logger log = Logger.getLogger(OkHttpClientFactory.class.getName()); - public static OkHttpClient createHttpClient(VaultRuntimeConfig serverConfig) { + public static OkHttpClient createHttpClient(VaultRuntimeConfig serverConfig, TlsConfig tlsConfig) { OkHttpClient.Builder builder = new OkHttpClient.Builder() .connectTimeout(serverConfig.connectTimeout) @@ -40,7 +41,8 @@ public static OkHttpClient createHttpClient(VaultRuntimeConfig serverConfig) { } try { - if (serverConfig.tls.skipVerify) { + boolean trustAll = serverConfig.tls.skipVerify.isPresent() ? serverConfig.tls.skipVerify.get() : tlsConfig.trustAll; + if (trustAll) { skipVerify(builder); } else if (serverConfig.tls.caCert.isPresent()) { cacert(builder, serverConfig.tls.caCert.get()); diff --git a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/client/OkHttpVaultClient.java b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/client/OkHttpVaultClient.java index 24f8682e9f459..74fcc4757b40b 100644 --- a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/client/OkHttpVaultClient.java +++ b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/client/OkHttpVaultClient.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import io.quarkus.runtime.TlsConfig; import io.quarkus.vault.VaultException; import io.quarkus.vault.runtime.client.dto.auth.VaultAppRoleAuth; import io.quarkus.vault.runtime.client.dto.auth.VaultAppRoleAuthBody; @@ -83,8 +84,8 @@ public class OkHttpVaultClient implements VaultClient { private String kubernetesAuthMountPath; private ObjectMapper mapper = new ObjectMapper(); - public OkHttpVaultClient(VaultRuntimeConfig serverConfig) { - this.client = createHttpClient(serverConfig); + public OkHttpVaultClient(VaultRuntimeConfig serverConfig, TlsConfig tlsConfig) { + this.client = createHttpClient(serverConfig, tlsConfig); this.url = serverConfig.url.get(); this.mapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false); this.mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); diff --git a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/config/VaultConfigSource.java b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/config/VaultConfigSource.java index decd992ee5ffe..b79e35062b24f 100644 --- a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/config/VaultConfigSource.java +++ b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/config/VaultConfigSource.java @@ -10,7 +10,6 @@ import static io.quarkus.vault.runtime.config.VaultRuntimeConfig.DEFAULT_READ_TIMEOUT; import static io.quarkus.vault.runtime.config.VaultRuntimeConfig.DEFAULT_RENEW_GRACE_PERIOD; import static io.quarkus.vault.runtime.config.VaultRuntimeConfig.DEFAULT_SECRET_CONFIG_CACHE_PERIOD; -import static io.quarkus.vault.runtime.config.VaultRuntimeConfig.DEFAULT_TLS_SKIP_VERIFY; import static io.quarkus.vault.runtime.config.VaultRuntimeConfig.DEFAULT_TLS_USE_KUBERNETES_CACERT; import static io.quarkus.vault.runtime.config.VaultRuntimeConfig.KV_SECRET_ENGINE_VERSION_V2; import static java.lang.Boolean.parseBoolean; @@ -43,6 +42,7 @@ import org.eclipse.microprofile.config.spi.ConfigSource; import org.jboss.logging.Logger; +import io.quarkus.runtime.TlsConfig; import io.quarkus.runtime.configuration.DurationConverter; import io.quarkus.vault.VaultException; import io.quarkus.vault.runtime.LogConfidentialityLevel; @@ -62,6 +62,7 @@ public class VaultConfigSource implements ConfigSource { private AtomicReference>> cache = new AtomicReference<>(null); private AtomicReference serverConfig = new AtomicReference<>(null); private AtomicReference buildServerConfig = new AtomicReference<>(null); + private AtomicReference tlsConfig = new AtomicReference<>(null); private AtomicBoolean init = new AtomicBoolean(false); private int ordinal; @@ -155,10 +156,11 @@ private VaultManager getVaultManager() { VaultBuildTimeConfig buildTimeConfig = getBuildtimeConfig(); VaultRuntimeConfig serverConfig = getRuntimeConfig(); + TlsConfig tlsConfig = getTlsConfig(); // init at most once if (init.compareAndSet(false, true)) { - VaultManager.init(buildTimeConfig, serverConfig); + VaultManager.init(buildTimeConfig, serverConfig, tlsConfig); } return VaultManager.getInstance(); @@ -172,6 +174,10 @@ private VaultBuildTimeConfig getBuildtimeConfig() { return getConfig(this.buildServerConfig, () -> loadBuildtimeConfig(), "buildtime"); } + private TlsConfig getTlsConfig() { + return getConfig(this.tlsConfig, () -> loadTlsConfig(), "tls"); + } + private T getConfig(AtomicReference ref, Supplier supplier, String name) { T config = ref.get(); if (config != null) { @@ -237,7 +243,7 @@ private VaultRuntimeConfig loadRuntimeConfig() { serverConfig.kvSecretEngineMountPath = getVaultProperty("kv-secret-engine-mount-path", DEFAULT_KV_SECRET_ENGINE_MOUNT_PATH); serverConfig.secretConfigKvPath = getOptionalListProperty("secret-config-kv-path"); - serverConfig.tls.skipVerify = parseBoolean(getVaultProperty("tls.skip-verify", DEFAULT_TLS_SKIP_VERIFY)); + serverConfig.tls.skipVerify = getOptionalVaultProperty("tls.skip-verify").map(Boolean::parseBoolean); serverConfig.tls.useKubernetesCaCert = parseBoolean( getVaultProperty("tls.use-kubernetes-ca-cert", DEFAULT_TLS_USE_KUBERNETES_CACERT)); serverConfig.tls.caCert = getOptionalVaultProperty("tls.ca-cert"); @@ -251,6 +257,12 @@ private VaultRuntimeConfig loadRuntimeConfig() { return serverConfig; } + private TlsConfig loadTlsConfig() { + TlsConfig tlsConfig = new TlsConfig(); + tlsConfig.trustAll = Boolean.parseBoolean(getProperty("quarkus.tls.trust-all", "false", 0)); + return tlsConfig; + } + private VaultMapConfigParser createCredentialProviderConfigParser() { return new VaultMapConfigParser<>(CREDENTIALS_PATTERN, this::getCredentialsProviderConfig, getConfigSourceStream()); } diff --git a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/config/VaultRuntimeConfig.java b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/config/VaultRuntimeConfig.java index 879f02ad1bd43..130d42b25270a 100644 --- a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/config/VaultRuntimeConfig.java +++ b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/config/VaultRuntimeConfig.java @@ -30,7 +30,6 @@ public class VaultRuntimeConfig { public static final String KUBERNETES_CACERT = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"; public static final String DEFAULT_CONNECT_TIMEOUT = "5S"; public static final String DEFAULT_READ_TIMEOUT = "1S"; - public static final String DEFAULT_TLS_SKIP_VERIFY = "false"; public static final String DEFAULT_TLS_USE_KUBERNETES_CACERT = "true"; public static final String DEFAULT_KUBERNETES_AUTH_MOUNT_PATH = "auth/kubernetes"; diff --git a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/config/VaultTlsConfig.java b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/config/VaultTlsConfig.java index ae253f46d85a8..bb1931d3f4e14 100644 --- a/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/config/VaultTlsConfig.java +++ b/extensions/vault/runtime/src/main/java/io/quarkus/vault/runtime/config/VaultTlsConfig.java @@ -1,6 +1,5 @@ package io.quarkus.vault.runtime.config; -import static io.quarkus.vault.runtime.config.VaultRuntimeConfig.DEFAULT_TLS_SKIP_VERIFY; import static io.quarkus.vault.runtime.config.VaultRuntimeConfig.DEFAULT_TLS_USE_KUBERNETES_CACERT; import java.util.Optional; @@ -18,8 +17,8 @@ public class VaultTlsConfig { * certificate presented by Vault. This is discouraged in production because it allows man in the middle * type of attacks. */ - @ConfigItem(defaultValue = DEFAULT_TLS_SKIP_VERIFY) - public boolean skipVerify; + @ConfigItem + public Optional skipVerify = Optional.empty(); /** * Certificate bundle used to validate TLS communications with Vault. diff --git a/extensions/vault/runtime/src/test/java/io/quarkus/vault/runtime/VaultAuthManagerTest.java b/extensions/vault/runtime/src/test/java/io/quarkus/vault/runtime/VaultAuthManagerTest.java index 6dea66650bcf0..c00739aaff270 100644 --- a/extensions/vault/runtime/src/test/java/io/quarkus/vault/runtime/VaultAuthManagerTest.java +++ b/extensions/vault/runtime/src/test/java/io/quarkus/vault/runtime/VaultAuthManagerTest.java @@ -11,6 +11,7 @@ import org.junit.jupiter.api.Test; +import io.quarkus.runtime.TlsConfig; import io.quarkus.vault.runtime.client.OkHttpVaultClient; import io.quarkus.vault.runtime.client.VaultClientException; import io.quarkus.vault.runtime.client.dto.auth.VaultLookupSelf; @@ -28,6 +29,7 @@ public class VaultAuthManagerTest { VaultRuntimeConfig config = createConfig(); + TlsConfig tlsConfig = new TlsConfig(); AtomicBoolean lookupSelfShouldReturn403 = new AtomicBoolean(false); OkHttpVaultClient vaultClient = createVaultClient(); VaultAuthManager vaultAuthManager = new VaultAuthManager(vaultClient, config); @@ -107,7 +109,7 @@ private VaultRuntimeConfig createConfig() { config.authentication.userpass.passwordWrappingToken = Optional.empty(); config.connectTimeout = Duration.ofSeconds(1); config.readTimeout = Duration.ofSeconds(1); - config.tls.skipVerify = true; + config.tls.skipVerify = Optional.of(true); config.logConfidentialityLevel = LogConfidentialityLevel.LOW; config.renewGracePeriod = Duration.ofSeconds(3); return config; @@ -117,7 +119,7 @@ private VaultRuntimeConfig createConfig() { } private OkHttpVaultClient createVaultClient() { - return new OkHttpVaultClient(config) { + return new OkHttpVaultClient(config, tlsConfig) { @Override public VaultUserPassAuth loginUserPass(String user, String password) { return vaultUserPassAuth; diff --git a/extensions/vault/runtime/src/test/java/io/quarkus/vault/runtime/VaultDbManagerTest.java b/extensions/vault/runtime/src/test/java/io/quarkus/vault/runtime/VaultDbManagerTest.java index 2487eac9d33c8..c1ac5fdaede0d 100644 --- a/extensions/vault/runtime/src/test/java/io/quarkus/vault/runtime/VaultDbManagerTest.java +++ b/extensions/vault/runtime/src/test/java/io/quarkus/vault/runtime/VaultDbManagerTest.java @@ -14,6 +14,7 @@ import org.junit.jupiter.api.Test; +import io.quarkus.runtime.TlsConfig; import io.quarkus.vault.runtime.client.OkHttpVaultClient; import io.quarkus.vault.runtime.client.VaultClientException; import io.quarkus.vault.runtime.client.dto.database.VaultDatabaseCredentials; @@ -30,6 +31,7 @@ public class VaultDbManagerTest { VaultRuntimeConfig config = createConfig(); + TlsConfig tlsConfig = new TlsConfig(); VaultDatabaseCredentials credentials = new VaultDatabaseCredentials(); VaultLeasesLookup vaultLeasesLookup = new VaultLeasesLookup(); AtomicBoolean lookupLeaseShouldReturn400 = new AtomicBoolean(false); @@ -113,7 +115,7 @@ private VaultRuntimeConfig createConfig() { config.authentication.userpass.passwordWrappingToken = Optional.empty(); config.connectTimeout = Duration.ofSeconds(1); config.readTimeout = Duration.ofSeconds(1); - config.tls.skipVerify = true; + config.tls.skipVerify = Optional.of(true); config.logConfidentialityLevel = LogConfidentialityLevel.LOW; config.renewGracePeriod = Duration.ofSeconds(3); return config; @@ -123,7 +125,7 @@ private VaultRuntimeConfig createConfig() { } private OkHttpVaultClient createVaultClient() { - return new OkHttpVaultClient(config) { + return new OkHttpVaultClient(config, tlsConfig) { @Override public VaultDatabaseCredentials generateDatabaseCredentials(String token, String databaseCredentialsRole) { return credentials; diff --git a/integration-tests/rest-client/src/test/java/io/quarkus/it/rest/client/trustall/ExternalTlsTrustAllIT.java b/integration-tests/rest-client/src/test/java/io/quarkus/it/rest/client/trustall/ExternalTlsTrustAllIT.java new file mode 100644 index 0000000000000..d359a08de548b --- /dev/null +++ b/integration-tests/rest-client/src/test/java/io/quarkus/it/rest/client/trustall/ExternalTlsTrustAllIT.java @@ -0,0 +1,7 @@ +package io.quarkus.it.rest.client.trustall; + +import io.quarkus.test.junit.NativeImageTest; + +@NativeImageTest +public class ExternalTlsTrustAllIT extends ExternalTlsTrustAllTestCase { +} diff --git a/integration-tests/rest-client/src/test/java/io/quarkus/it/rest/client/trustall/ExternalTlsTrustAllTestCase.java b/integration-tests/rest-client/src/test/java/io/quarkus/it/rest/client/trustall/ExternalTlsTrustAllTestCase.java new file mode 100644 index 0000000000000..ba89527182f5d --- /dev/null +++ b/integration-tests/rest-client/src/test/java/io/quarkus/it/rest/client/trustall/ExternalTlsTrustAllTestCase.java @@ -0,0 +1,23 @@ +package io.quarkus.it.rest.client.trustall; + +import static io.restassured.RestAssured.when; +import static org.hamcrest.Matchers.is; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +@QuarkusTestResource(ExternalTlsTrustAllTestResource.class) +public class ExternalTlsTrustAllTestCase { + + @Test + public void restClient() { + when() + .get("/wrong-host") + .then() + .statusCode(200) + .body(is("200")); + } +} diff --git a/integration-tests/rest-client/src/test/java/io/quarkus/it/rest/client/trustall/ExternalTlsTrustAllTestResource.java b/integration-tests/rest-client/src/test/java/io/quarkus/it/rest/client/trustall/ExternalTlsTrustAllTestResource.java new file mode 100644 index 0000000000000..2a55b750ba3f7 --- /dev/null +++ b/integration-tests/rest-client/src/test/java/io/quarkus/it/rest/client/trustall/ExternalTlsTrustAllTestResource.java @@ -0,0 +1,23 @@ +package io.quarkus.it.rest.client.trustall; + +import java.util.HashMap; +import java.util.Map; + +import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; + +public class ExternalTlsTrustAllTestResource implements QuarkusTestResourceLifecycleManager { + + @Override + public Map start() { + Map result = new HashMap<>(); + result.put("wrong-host/mp-rest/trustStore", System.getProperty("rest-client.trustStore")); + result.put("wrong-host/mp-rest/trustStorePassword", System.getProperty("rest-client.trustStorePassword")); + result.put("quarkus.tls.trust-all", "true"); + return result; + } + + @Override + public void stop() { + + } +} diff --git a/integration-tests/vault/src/test/resources/application-vault-multi-path.properties b/integration-tests/vault/src/test/resources/application-vault-multi-path.properties index 8a2452d1fc34f..54fc75776fd26 100644 --- a/integration-tests/vault/src/test/resources/application-vault-multi-path.properties +++ b/integration-tests/vault/src/test/resources/application-vault-multi-path.properties @@ -4,7 +4,7 @@ quarkus.vault.authentication.userpass.password=sinclair quarkus.vault.secret-config-kv-path=multi/default1,multi/default2 quarkus.vault.secret-config-kv-path.singer=multi/singer1,multi/singer2 -quarkus.vault.tls.skip-verify=true +quarkus.tls.trust-all=true # CI can sometimes be slow, there is no need to fail a test if Vault doesn't respond in 1 second which is the default quarkus.vault.read-timeout=5S diff --git a/test-framework/vault/src/main/java/io/quarkus/vault/test/VaultTestExtension.java b/test-framework/vault/src/main/java/io/quarkus/vault/test/VaultTestExtension.java index a14138d37b1e1..3ddb7568e0947 100644 --- a/test-framework/vault/src/main/java/io/quarkus/vault/test/VaultTestExtension.java +++ b/test-framework/vault/src/main/java/io/quarkus/vault/test/VaultTestExtension.java @@ -46,6 +46,7 @@ import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.containers.output.OutputFrame; +import io.quarkus.runtime.TlsConfig; import io.quarkus.vault.VaultException; import io.quarkus.vault.VaultKVSecretEngine; import io.quarkus.vault.runtime.VaultManager; @@ -168,7 +169,7 @@ private static VaultManager createVaultManager() { VaultRuntimeConfig serverConfig = new VaultRuntimeConfig(); serverConfig.tls = new VaultTlsConfig(); serverConfig.url = getVaultUrl(); - serverConfig.tls.skipVerify = true; + serverConfig.tls.skipVerify = Optional.of(true); serverConfig.tls.caCert = Optional.empty(); serverConfig.connectTimeout = Duration.ofSeconds(5); serverConfig.readTimeout = Duration.ofSeconds(1); @@ -177,8 +178,9 @@ private static VaultManager createVaultManager() { VaultBuildTimeConfig buildTimeConfig = new VaultBuildTimeConfig(); buildTimeConfig.health = new HealthConfig(); + TlsConfig tlsConfig = new TlsConfig(); - return new VaultManager(buildTimeConfig, serverConfig, new TestVaultClient(serverConfig)); + return new VaultManager(buildTimeConfig, serverConfig, new TestVaultClient(serverConfig, tlsConfig), tlsConfig); } private static Optional getVaultUrl() { diff --git a/test-framework/vault/src/main/java/io/quarkus/vault/test/client/TestVaultClient.java b/test-framework/vault/src/main/java/io/quarkus/vault/test/client/TestVaultClient.java index 89ba776c05130..bfd3fd71adf48 100644 --- a/test-framework/vault/src/main/java/io/quarkus/vault/test/client/TestVaultClient.java +++ b/test-framework/vault/src/main/java/io/quarkus/vault/test/client/TestVaultClient.java @@ -1,5 +1,6 @@ package io.quarkus.vault.test.client; +import io.quarkus.runtime.TlsConfig; import io.quarkus.vault.runtime.VaultManager; import io.quarkus.vault.runtime.client.OkHttpVaultClient; import io.quarkus.vault.runtime.client.dto.transit.VaultTransitRandomBody; @@ -13,11 +14,11 @@ public class TestVaultClient extends OkHttpVaultClient { public TestVaultClient() { - this(VaultManager.getInstance().getServerConfig()); + this(VaultManager.getInstance().getServerConfig(), VaultManager.getInstance().getTlsConfig()); } - public TestVaultClient(VaultRuntimeConfig serverConfig) { - super(serverConfig); + public TestVaultClient(VaultRuntimeConfig serverConfig, TlsConfig tlsConfig) { + super(serverConfig, tlsConfig); } public VaultAppRoleSecretId generateAppRoleSecretId(String token, String roleName) {