Skip to content

Commit

Permalink
Merge pull request #43148 from michalvavrik/feature/oidc-tls-registry
Browse files Browse the repository at this point in the history
Add support for the TLS registry to OIDC and OIDC client extensions
  • Loading branch information
sberyozkin authored Sep 10, 2024
2 parents afb656f + 46f3904 commit 082433a
Show file tree
Hide file tree
Showing 15 changed files with 509 additions and 315 deletions.
19 changes: 11 additions & 8 deletions docs/src/main/asciidoc/security-oidc-code-flow-authentication.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -266,21 +266,24 @@ The following example shows how you can configure `quarkus-oidc` to support `mTL

[source,properties]
----
quarkus.oidc.tls.verification=certificate-validation
quarkus.oidc.tls.tls-configuration-name=oidc
# configure hostname verification if necessary
#quarkus.tls.oidc.hostname-verification-algorithm=NONE
# Keystore configuration
quarkus.oidc.tls.key-store-file=client-keystore.jks
quarkus.oidc.tls.key-store-password=${key-store-password}
quarkus.tls.oidc.key-store.p12.path=client-keystore.p12
quarkus.tls.oidc.key-store.p12.password=${key-store-password}
# Add more keystore properties if needed:
#quarkus.oidc.tls.key-store-alias=keyAlias
#quarkus.oidc.tls.key-store-alias-password=keyAliasPassword
#quarkus.tls.oidc.key-store.p12.alias=keyAlias
#quarkus.tls.oidc.key-store.p12.alias-password=keyAliasPassword
# Truststore configuration
quarkus.oidc.tls.trust-store-file=client-truststore.jks
quarkus.oidc.tls.trust-store-password=${trust-store-password}
quarkus.tls.oidc.trust-store.p12.path=client-truststore.p12
quarkus.tls.oidc.trust-store.p12.password=${trust-store-password}
# Add more truststore properties if needed:
#quarkus.oidc.tls.trust-store-alias=certAlias
#quarkus.tls.oidc.trust-store.p12.alias=certAlias
----

==== POST query
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -917,21 +917,24 @@ Some OpenID Connect Providers require that a client is authenticated as part of

[source,properties]
----
quarkus.oidc-client.tls.verification=certificate-validation
quarkus.oidc-client.tls.tls-configuration-name=oidc-client
# configure hostname verification if necessary
#quarkus.tls.oidc-client.hostname-verification-algorithm=NONE
# Keystore configuration
quarkus.oidc-client.tls.key-store-file=client-keystore.jks
quarkus.oidc-client.tls.key-store-password=${key-store-password}
quarkus.tls.oidc-client.key-store.p12.path=client-keystore.p12
quarkus.tls.oidc-client.key-store.p12.password=${key-store-password}
# Add more keystore properties if needed:
#quarkus.oidc-client.tls.key-store-alias=keyAlias
#quarkus.oidc-client.tls.key-store-alias-password=keyAliasPassword
#quarkus.tls.oidc-client.key-store.p12.alias=keyAlias
#quarkus.tls.oidc-client.key-store.p12.alias-password=keyAliasPassword
# Truststore configuration
quarkus.oidc-client.tls.trust-store-file=client-truststore.jks
quarkus.oidc-client.tls.trust-store-password=${trust-store-password}
quarkus.tls.oidc-client.trust-store.p12.path=client-truststore.p12
quarkus.tls.oidc-client.trust-store.p12.password=${trust-store-password}
# Add more truststore properties if needed:
#quarkus.oidc-client.tls.trust-store-alias=certAlias
#quarkus.tls.oidc-client.trust-store.p12.alias=certAlias
----

=== OIDC Client SPI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
import io.quarkus.keycloak.pep.PolicyEnforcerResolver;
import io.quarkus.keycloak.pep.TenantPolicyConfigResolver;
import io.quarkus.oidc.OidcTenantConfig;
import io.quarkus.oidc.common.runtime.OidcTlsSupport;
import io.quarkus.oidc.runtime.BlockingTaskRunner;
import io.quarkus.oidc.runtime.OidcConfig;
import io.quarkus.security.spi.runtime.BlockingSecurityExecutor;
import io.quarkus.tls.TlsConfiguration;
import io.quarkus.tls.TlsConfigurationRegistry;
import io.quarkus.vertx.http.runtime.HttpConfiguration;
import io.smallrye.mutiny.Uni;
Expand All @@ -34,7 +34,7 @@ public class DefaultPolicyEnforcerResolver implements PolicyEnforcerResolver {
private final Map<String, PolicyEnforcer> namedPolicyEnforcers;
private final PolicyEnforcer defaultPolicyEnforcer;
private final long readTimeout;
private final boolean globalTrustAll;
private final OidcTlsSupport tlsSupport;

DefaultPolicyEnforcerResolver(OidcConfig oidcConfig, KeycloakPolicyEnforcerConfig config,
HttpConfiguration httpConfiguration, BlockingSecurityExecutor blockingSecurityExecutor,
Expand All @@ -43,13 +43,15 @@ public class DefaultPolicyEnforcerResolver implements PolicyEnforcerResolver {
this.readTimeout = httpConfiguration.readTimeout.toMillis();

if (tlsConfigRegistryInstance.isResolvable()) {
this.globalTrustAll = tlsConfigRegistryInstance.get().getDefault().map(TlsConfiguration::isTrustAll).orElse(false);
this.tlsSupport = OidcTlsSupport.of(tlsConfigRegistryInstance.get());
} else {
this.globalTrustAll = false;
this.tlsSupport = OidcTlsSupport.empty();
}

this.defaultPolicyEnforcer = createPolicyEnforcer(oidcConfig.defaultTenant, config.defaultTenant(), globalTrustAll);
this.namedPolicyEnforcers = createNamedPolicyEnforcers(oidcConfig, config, globalTrustAll);
var defaultTenantTlsSupport = tlsSupport.forConfig(oidcConfig.defaultTenant.tls);
this.defaultPolicyEnforcer = createPolicyEnforcer(oidcConfig.defaultTenant, config.defaultTenant(),
defaultTenantTlsSupport);
this.namedPolicyEnforcers = createNamedPolicyEnforcers(oidcConfig, config, tlsSupport);
if (configResolver.isResolvable()) {
this.dynamicConfigResolver = configResolver.get();
this.requestContext = new BlockingTaskRunner<>(blockingSecurityExecutor);
Expand Down Expand Up @@ -97,13 +99,13 @@ private Uni<PolicyEnforcer> getDynamicPolicyEnforcer(RoutingContext routingConte
.onItem().ifNotNull().transform(new Function<KeycloakPolicyEnforcerTenantConfig, PolicyEnforcer>() {
@Override
public PolicyEnforcer apply(KeycloakPolicyEnforcerTenantConfig tenant) {
return createPolicyEnforcer(config, tenant, globalTrustAll);
return createPolicyEnforcer(config, tenant, tlsSupport.forConfig(config.tls));
}
});
}

private static Map<String, PolicyEnforcer> createNamedPolicyEnforcers(OidcConfig oidcConfig,
KeycloakPolicyEnforcerConfig config, boolean tlsConfigTrustAll) {
KeycloakPolicyEnforcerConfig config, OidcTlsSupport tlsSupport) {
if (config.namedTenants().isEmpty()) {
return Map.of();
}
Expand All @@ -112,8 +114,9 @@ private static Map<String, PolicyEnforcer> createNamedPolicyEnforcers(OidcConfig
for (Map.Entry<String, KeycloakPolicyEnforcerTenantConfig> tenant : config.namedTenants().entrySet()) {
OidcTenantConfig oidcTenantConfig = getOidcTenantConfig(oidcConfig, tenant.getKey());
policyEnforcerTenants.put(tenant.getKey(),
createPolicyEnforcer(oidcTenantConfig, tenant.getValue(), tlsConfigTrustAll));
createPolicyEnforcer(oidcTenantConfig, tenant.getValue(), tlsSupport.forConfig(oidcTenantConfig.tls)));
}
return Map.copyOf(policyEnforcerTenants);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.quarkus.oidc.OIDCException;
import io.quarkus.oidc.OidcTenantConfig;
import io.quarkus.oidc.common.runtime.OidcCommonConfig;
import io.quarkus.oidc.common.runtime.OidcTlsSupport.TlsConfigSupport;
import io.quarkus.oidc.runtime.OidcConfig;
import io.quarkus.runtime.configuration.ConfigurationException;

Expand All @@ -30,7 +31,7 @@ private KeycloakPolicyEnforcerUtil() {

static PolicyEnforcer createPolicyEnforcer(OidcTenantConfig oidcConfig,
KeycloakPolicyEnforcerTenantConfig keycloakPolicyEnforcerConfig,
boolean tlsConfigTrustAll) {
TlsConfigSupport tlsConfigSupport) {

if (oidcConfig.applicationType
.orElse(OidcTenantConfig.ApplicationType.SERVICE) == OidcTenantConfig.ApplicationType.WEB_APP
Expand All @@ -51,18 +52,20 @@ static PolicyEnforcer createPolicyEnforcer(OidcTenantConfig oidcConfig,
adapterConfig.setResource(oidcConfig.getClientId().get());
adapterConfig.setCredentials(getCredentials(oidcConfig));

boolean trustAll = oidcConfig.tls.getVerification().isPresent()
? oidcConfig.tls.getVerification().get() == OidcCommonConfig.Tls.Verification.NONE
: tlsConfigTrustAll;
if (trustAll) {
adapterConfig.setDisableTrustManager(true);
adapterConfig.setAllowAnyHostname(true);
} else if (oidcConfig.tls.trustStoreFile.isPresent()) {
adapterConfig.setTruststore(oidcConfig.tls.trustStoreFile.get().toString());
adapterConfig.setTruststorePassword(oidcConfig.tls.trustStorePassword.orElse("password"));
if (OidcCommonConfig.Tls.Verification.CERTIFICATE_VALIDATION == oidcConfig.tls.verification
.orElse(OidcCommonConfig.Tls.Verification.REQUIRED)) {
if (!tlsConfigSupport.useTlsRegistry()) {
boolean trustAll = oidcConfig.tls.getVerification().isPresent()
? oidcConfig.tls.getVerification().get() == OidcCommonConfig.Tls.Verification.NONE
: tlsConfigSupport.isGlobalTrustAll();
if (trustAll) {
adapterConfig.setDisableTrustManager(true);
adapterConfig.setAllowAnyHostname(true);
} else if (oidcConfig.tls.trustStoreFile.isPresent()) {
adapterConfig.setTruststore(oidcConfig.tls.trustStoreFile.get().toString());
adapterConfig.setTruststorePassword(oidcConfig.tls.trustStorePassword.orElse("password"));
if (OidcCommonConfig.Tls.Verification.CERTIFICATE_VALIDATION == oidcConfig.tls.verification
.orElse(OidcCommonConfig.Tls.Verification.REQUIRED)) {
adapterConfig.setAllowAnyHostname(true);
}
}
}
adapterConfig.setConnectionPoolSize(keycloakPolicyEnforcerConfig.connectionPoolSize());
Expand All @@ -86,7 +89,7 @@ static PolicyEnforcer createPolicyEnforcer(OidcTenantConfig oidcConfig,
.credentials(adapterConfig.getCredentials())
.bearerOnly(adapterConfig.isBearerOnly())
.enforcerConfig(enforcerConfig)
.httpClient(new HttpClientBuilder().build(adapterConfig))
.httpClient(new HttpClientBuilder().sslContext(tlsConfigSupport.getSslContext()).build(adapterConfig))
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
import io.quarkus.oidc.common.OidcRequestContextProperties;
import io.quarkus.oidc.common.OidcRequestFilter;
import io.quarkus.oidc.common.runtime.OidcCommonUtils;
import io.quarkus.oidc.common.runtime.OidcTlsSupport;
import io.quarkus.runtime.annotations.Recorder;
import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.tls.TlsConfiguration;
import io.quarkus.tls.TlsConfigurationRegistry;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;
Expand All @@ -38,24 +38,24 @@ public class OidcClientRegistrationRecorder {

public OidcClientRegistrations setup(OidcClientRegistrationsConfig oidcClientRegsConfig,
Supplier<Vertx> vertx, Supplier<TlsConfigurationRegistry> registrySupplier) {
var defaultTlsConfiguration = registrySupplier.get().getDefault().orElse(null);

var tlsSupport = OidcTlsSupport.of(registrySupplier);
OidcClientRegistration defaultClientReg = createOidcClientRegistration(oidcClientRegsConfig.defaultClientRegistration,
defaultTlsConfiguration, vertx);
tlsSupport, vertx);

Map<String, OidcClientRegistration> staticOidcClientRegs = new HashMap<>();

for (Map.Entry<String, OidcClientRegistrationConfig> config : oidcClientRegsConfig.namedClientRegistrations
.entrySet()) {
staticOidcClientRegs.put(config.getKey(),
createOidcClientRegistration(config.getValue(), defaultTlsConfiguration, vertx));
createOidcClientRegistration(config.getValue(), tlsSupport, vertx));
}

return new OidcClientRegistrationsImpl(defaultClientReg, staticOidcClientRegs,
new Function<OidcClientRegistrationConfig, Uni<OidcClientRegistration>>() {
@Override
public Uni<OidcClientRegistration> apply(OidcClientRegistrationConfig config) {
return createOidcClientRegistrationUni(config, defaultTlsConfiguration, vertx);
return createOidcClientRegistrationUni(config, tlsSupport, vertx);
}
});
}
Expand Down Expand Up @@ -86,13 +86,13 @@ public OidcClientRegistrations get() {
}

public static OidcClientRegistration createOidcClientRegistration(OidcClientRegistrationConfig oidcConfig,
TlsConfiguration tlsConfig, Supplier<Vertx> vertxSupplier) {
return createOidcClientRegistrationUni(oidcConfig, tlsConfig, vertxSupplier).await()
OidcTlsSupport tlsSupport, Supplier<Vertx> vertxSupplier) {
return createOidcClientRegistrationUni(oidcConfig, tlsSupport, vertxSupplier).await()
.atMost(oidcConfig.connectionTimeout);
}

public static Uni<OidcClientRegistration> createOidcClientRegistrationUni(OidcClientRegistrationConfig oidcConfig,
TlsConfiguration tlsConfig, Supplier<Vertx> vertxSupplier) {
OidcTlsSupport tlsSupport, Supplier<Vertx> vertxSupplier) {
if (!oidcConfig.registrationEnabled) {
String message = String.format("'%s' client registration configuration is disabled", "");
LOG.debug(message);
Expand All @@ -117,7 +117,7 @@ public static Uni<OidcClientRegistration> createOidcClientRegistrationUni(OidcCl

WebClientOptions options = new WebClientOptions();

OidcCommonUtils.setHttpClientOptions(oidcConfig, options, tlsConfig);
OidcCommonUtils.setHttpClientOptions(oidcConfig, options, tlsSupport.forConfig(oidcConfig.tls));

final io.vertx.mutiny.core.Vertx vertx = new io.vertx.mutiny.core.Vertx(vertxSupplier.get());
WebClient client = WebClient.create(vertx, options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
import io.quarkus.oidc.common.OidcRequestFilter;
import io.quarkus.oidc.common.runtime.OidcCommonUtils;
import io.quarkus.oidc.common.runtime.OidcConstants;
import io.quarkus.oidc.common.runtime.OidcTlsSupport;
import io.quarkus.runtime.annotations.Recorder;
import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.tls.TlsConfiguration;
import io.quarkus.tls.TlsConfigurationRegistry;
import io.smallrye.mutiny.Uni;
import io.vertx.core.Vertx;
Expand All @@ -46,25 +46,23 @@ public class OidcClientRecorder {
private static OidcClients setup(OidcClientsConfig oidcClientsConfig, Supplier<Vertx> vertx,
Supplier<TlsConfigurationRegistry> registrySupplier) {

var tlsSupport = OidcTlsSupport.of(registrySupplier);
String defaultClientId = oidcClientsConfig.defaultClient.getId().orElse(DEFAULT_OIDC_CLIENT_ID);
var defaultTlsConfiguration = registrySupplier.get().getDefault().orElse(null);
OidcClient defaultClient = createOidcClient(oidcClientsConfig.defaultClient, defaultClientId, vertx,
defaultTlsConfiguration);
OidcClient defaultClient = createOidcClient(oidcClientsConfig.defaultClient, defaultClientId, vertx, tlsSupport);

Map<String, OidcClient> staticOidcClients = new HashMap<>();

for (Map.Entry<String, OidcClientConfig> config : oidcClientsConfig.namedClients.entrySet()) {
OidcCommonUtils.verifyConfigurationId(defaultClientId, config.getKey(), config.getValue().getId());
staticOidcClients.put(config.getKey(),
createOidcClient(config.getValue(), config.getKey(), vertx, defaultTlsConfiguration));
createOidcClient(config.getValue(), config.getKey(), vertx, tlsSupport));
}

return new OidcClientsImpl(defaultClient, staticOidcClients,
new Function<OidcClientConfig, Uni<OidcClient>>() {
@Override
public Uni<OidcClient> apply(OidcClientConfig config) {
return createOidcClientUni(config, config.getId().get(), vertx,
registrySupplier.get().getDefault().orElse(null));
return createOidcClientUni(config, config.getId().get(), vertx, OidcTlsSupport.of(registrySupplier));
}
});
}
Expand Down Expand Up @@ -101,13 +99,13 @@ public OidcClients get() {
}

protected static OidcClient createOidcClient(OidcClientConfig oidcConfig, String oidcClientId, Supplier<Vertx> vertx,
TlsConfiguration defaultTlsConfiguration) {
return createOidcClientUni(oidcConfig, oidcClientId, vertx, defaultTlsConfiguration).await()
OidcTlsSupport tlsSupport) {
return createOidcClientUni(oidcConfig, oidcClientId, vertx, tlsSupport).await()
.atMost(oidcConfig.connectionTimeout);
}

protected static Uni<OidcClient> createOidcClientUni(OidcClientConfig oidcConfig, String oidcClientId,
Supplier<Vertx> vertx, TlsConfiguration defaultTlsConfiguration) {
Supplier<Vertx> vertx, OidcTlsSupport tlsSupport) {
if (!oidcConfig.isClientEnabled()) {
String message = String.format("'%s' client configuration is disabled", oidcClientId);
LOG.debug(message);
Expand All @@ -132,7 +130,7 @@ protected static Uni<OidcClient> createOidcClientUni(OidcClientConfig oidcConfig

WebClientOptions options = new WebClientOptions();

OidcCommonUtils.setHttpClientOptions(oidcConfig, options, defaultTlsConfiguration);
OidcCommonUtils.setHttpClientOptions(oidcConfig, options, tlsSupport.forConfig(oidcConfig.tls));

var mutinyVertx = new io.vertx.mutiny.core.Vertx(vertx.get());
WebClient client = WebClient.create(mutinyVertx, options);
Expand Down
Loading

0 comments on commit 082433a

Please sign in to comment.