Skip to content

Commit

Permalink
Merge pull request #43156 from gsmet/3.14.3-backports-2
Browse files Browse the repository at this point in the history
[3.14] 3.14.3 backports 2
  • Loading branch information
gsmet authored Sep 10, 2024
2 parents 333b60d + 8936373 commit 245285f
Show file tree
Hide file tree
Showing 28 changed files with 357 additions and 56 deletions.
2 changes: 1 addition & 1 deletion bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
<cronutils.version>9.2.1</cronutils.version>
<quartz.version>2.3.2</quartz.version>
<h2.version>2.3.232</h2.version> <!-- When updating, needs to be matched in io.quarkus.hibernate.orm.runtime.config.DialectVersions
and dependencies jts-core and lucene-core need to be updated in extensions/jdbc/jdbc-h2/runtime/pom.xml -->
and the dependency jts-core needs to be updated in extensions/jdbc/jdbc-h2/runtime/pom.xml -->
<postgresql-jdbc.version>42.7.4</postgresql-jdbc.version>
<mariadb-jdbc.version>3.4.1</mariadb-jdbc.version>
<mysql-jdbc.version>8.3.0</mysql-jdbc.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,11 @@ default String getEffectiveImage() {
* If errors should be reported at runtime. This is a more relaxed setting, however it is not recommended as it
* means
* your application may fail at runtime if an unsupported feature is used by accident.
*
* Note that the use of this flag may result in build time failures due to {@code ClassNotFoundException}s.
* Reason most likely being that the Quarkus extension already optimized it away or do not actually need it.
* In such cases you should explicitly add the corresponding dependency providing the missing classes as a
* dependency to your project.
*/
@WithDefault("false")
boolean reportErrorsAtRuntime();
Expand Down
75 changes: 74 additions & 1 deletion docs/src/main/asciidoc/qute-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2228,7 +2228,7 @@ Quarkus provides a set of built-in extension methods.

TIP: A map value can be also accessed directly: `{map.myKey}`. Use the bracket notation for keys that are not legal identifiers: `{map['my key']}`.

==== Lists
===== Lists

* `get(index)`: Returns the element at the specified position in a list
** `{list.get(0)}`
Expand Down Expand Up @@ -2654,6 +2654,79 @@ class DetailResource {

WARNING: Unlike with `@Inject` the templates obtained via `RestTemplate` are not validated, i.e. the build does not fail if a template does not exist.

[[vertx_integration]]
=== Vert.x Integration

If you want to use `io.vertx.core.json.JsonObject` as data in your templates, then you will need to add the `quarkus-vertx` extension to your build file if not already part of your dependencies (most applications use this extension by default).


[source,xml,role="primary maven-dependency"]
.pom.xml
----
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx</artifactId>
</dependency>
----

[source,gradle,role="secondary gradle-dependency"]
.build.gradle
----
implementation("io.quarkus:quarkus-vertx")
----

With this dependency included, we have a special value resolver for `io.vertx.core.json.JsonObject` which makes it possible to access the properties of a JSON object in a template:

.src/main/resources/templates/foo.txt
[source,text]
----
{tool.name}
{tool.fieldNames}
{tool.fields}
{tool.size}
{tool.empty}
{tool.isEmpty}
{tool.get('name')}
{tool.containsKey('name')}
----

.QuteVertxIntegration.java
[source,java]
----
import java.util.HashMap;
import jakarta.inject.Inject;
import io.vertx.core.json.JsonObject;
import io.quarkus.qute.Template;
public class QuteVertxIntegration {
@Inject
Template foo;
public String render() {
HashMap<String, Object> toolMap = new Map<String, Object>();
toolMap.put("name", "Roq");
JsonObject jsonObject = new JsonObject(toolMap);
return foo.data("tool", jsonObject).render();
}
}
----

The `QuteVertxIntegration#render()` output should look like:

[source,text]
----
Roq
[name]
[name]
1
false
false
Roq
true
----


=== Development Mode

In the development mode, all files located in `src/main/resources/templates` are watched for changes.
Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/security-jwt.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ To prevent it, set `quarkus.smallrye-jwt.blocking-authentication=true`.

=== Token Propagation

Please see the xref:security-openid-connect-client-reference.adoc#token-propagation[Token Propagation] section about the Bearer access token propagation to the downstream services.
Please see the xref:security-openid-connect-client-reference.adoc#token-propagation-rest[Token Propagation] section about the Bearer access token propagation to the downstream services.

[[integration-testing]]
=== Testing
Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/security-oidc-auth0-tutorial.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ In fact, the last code example, showing the injected `UserInfo`, is a concrete e
But what about propagating access tokens to some custom services ? It is very easy to achieve in Quarkus, both for the authorization code and bearer token flows. All you need to do is to create a REST Client interface for calling the service requiring a Bearer token access and annotate it with `@AccessToken` and the access token arriving to the front-end endpoint as the Auth0 Bearer access token or acquired by Quarkus after completing the Auth0 authorization code flow, will be propagated to the target microservice. This is as easy as it can get.

For examples of propagating access tokens, see the following sections in this tutorial.
For more information about token propagation, see xref:security-openid-connect-client-reference.adoc#reactive-token-propagation[OIDC token propagation].
For more information about token propagation, see xref:security-openid-connect-client-reference.adoc#token-propagation-rest[OIDC token propagation].

[[jwt-access-tokens]]
=== Access tokens in JWT format
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ quarkus.oidc.introspection-path=/protocol/openid-connect/tokens/introspect

=== Token propagation

For information about bearer access token propagation to the downstream services, see the xref:security-openid-connect-client-reference.adoc#token-propagation[Token propagation] section of the Quarkus "OpenID Connect (OIDC) and OAuth2 client and filters reference" guide.
For information about bearer access token propagation to the downstream services, see the xref:security-openid-connect-client-reference.adoc#token-propagation-rest[Token propagation] section of the Quarkus "OpenID Connect (OIDC) and OAuth2 client and filters reference" guide.

=== JWT token certificate chain

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1497,7 +1497,7 @@ TIP: You can listen to other security events as described in the xref:security-c

=== Propagating tokens to downstream services

For information about Authorization Code Flow access token propagation to downstream services, see the xref:security-openid-connect-client-reference.adoc#token-propagation[Token Propagation] section.
For information about Authorization Code Flow access token propagation to downstream services, see the xref:security-openid-connect-client-reference.adoc#token-propagation-rest[Token Propagation] section.


== Integration considerations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ quarkus.oidc-client.grant.type=refresh

Then you can use the `OidcClient.refreshTokens` method with a provided refresh token to get the access token.

Using the `urn:ietf:params:oauth:grant-type:token-exchange` or `urn:ietf:params:oauth:grant-type:jwt-bearer` grants might be required if you are building a complex microservices application and want to avoid the same `Bearer` token be propagated to and used by more than one service. See <<token-propagation-reactive,Token Propagation in MicroProfile RestClient Reactive filter>> and <<token-propagation,Token Propagation in MicroProfile RestClient filter>> for more details.
Using the `urn:ietf:params:oauth:grant-type:token-exchange` or `urn:ietf:params:oauth:grant-type:jwt-bearer` grants might be required if you are building a complex microservices application and want to avoid the same `Bearer` token be propagated to and used by more than one service. See <<token-propagation-rest,Token Propagation for Quarkus REST>> and <<token-propagation-resteasy,Token Propagation for RESTEasy Classic>> for more details.

Using `OidcClient` to support the `authorization code` grant might be required if, for some reason, you cannot use the xref:security-oidc-code-flow-authentication.adoc[Quarkus OIDC extension] to support Authorization Code Flow. If there is a very good reason for you to implement Authorization Code Flow, then you can configure `OidcClient` as follows:

Expand Down Expand Up @@ -1102,10 +1102,10 @@ public class OidcRequestCustomizer implements OidcRequestFilter {
}
----

[[token-propagation-reactive]]
== Token Propagation Reactive
[[token-propagation-rest]]
== Token Propagation for Quarkus REST

The `quarkus-rest-client-oidc-token-propagation` extension provides a REST Client, `io.quarkus.oidc.token.propagation.reactive.AccessTokenRequestReactiveFilter`, that simplifies the propagation of authentication information. This client propagates the xref:security-oidc-bearer-token-authentication.adoc[bearer token] present in the currently active request or the token acquired from the xref:security-oidc-code-flow-authentication.adoc[authorization code flow mechanism] as the HTTP `Authorization` header's `Bearer` scheme value.
The `quarkus-rest-client-oidc-token-propagation` extension provides a REST Client filter, `io.quarkus.oidc.token.propagation.reactive.AccessTokenRequestReactiveFilter`, that simplifies the propagation of authentication information. This client propagates the xref:security-oidc-bearer-token-authentication.adoc[bearer token] present in the currently active request or the token acquired from the xref:security-oidc-code-flow-authentication.adoc[authorization code flow mechanism] as the HTTP `Authorization` header's `Bearer` scheme value.

You can selectively register `AccessTokenRequestReactiveFilter` by using either `io.quarkus.oidc.token.propagation.AccessToken` or `org.eclipse.microprofile.rest.client.annotation.RegisterProvider` annotation, for example:

Expand Down Expand Up @@ -1178,8 +1178,8 @@ quarkus.resteasy-client-oidc-token-propagation.exchange-token=true

`AccessTokenRequestReactiveFilter` uses a default `OidcClient` by default. A named `OidcClient` can be selected with a `quarkus.rest-client-oidc-token-propagation.client-name` configuration property or with the `io.quarkus.oidc.token.propagation.AccessToken#exchangeTokenClient` annotation attribute.

[[token-propagation]]
== Token Propagation
[[token-propagation-resteasy]]
== Token Propagation for RESTEasy Classic

The `quarkus-resteasy-client-oidc-token-propagation` extension provides two Jakarta REST `jakarta.ws.rs.client.ClientRequestFilter` class implementations that simplify the propagation of authentication information.
`io.quarkus.oidc.token.propagation.AccessTokenRequestFilter` propagates the xref:security-oidc-bearer-token-authentication.adoc[Bearer token] present in the current active request or the token acquired from the xref:security-oidc-code-flow-authentication.adoc[Authorization code flow mechanism], as the HTTP `Authorization` header's `Bearer` scheme value.
Expand Down Expand Up @@ -1333,24 +1333,6 @@ As mentioned, use `AccessTokenRequestFilter` if you work with Keycloak or an Ope
You can generate the tokens as described in xref:security-oidc-bearer-token-authentication.adoc#bearer-token-integration-testing[OpenID Connect Bearer Token Integration testing] section.
Prepare the REST test endpoints. You can have the test front-end endpoint, which uses the injected MP REST client with a registered token propagation filter, call the downstream endpoint. For example, see the `integration-tests/resteasy-client-oidc-token-propagation` in the `main` Quarkus repository.

[[reactive-token-propagation]]
== Token Propagation Reactive

Add the following Maven Dependency:

[source,xml]
----
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-oidc-token-propagation</artifactId>
</dependency>
----

The `quarkus-rest-client-oidc-token-propagation` extension provides `io.quarkus.oidc.token.propagation.reactive.AccessTokenRequestReactiveFilter` which can be used to propagate the current `Bearer` or `Authorization Code Flow` access tokens.

The `quarkus-rest-client-oidc-token-propagation` extension (as opposed to the non-reactive `quarkus-resteasy-client-oidc-token-propagation` extension) does not currently support the exchanging or resigning of the tokens before the propagation.
However, these features might be added in the future.

ifndef::no-quarkus-oidc-client-graphql[]
[[quarkus-oidc-client-graphql]]
== GraphQL client integration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ As mentioned in the xref:security-oidc-code-flow-authentication.adoc[OIDC code f
It is this access token that has to be propagated to services such as `Google Calendar`, or `Spotify Playlists` for the currently authenticated user to be able to use such services.

You do not have to bring provider-specific libraries in order to achieve this, but instead you can use a reactive `Token Propagation` filter, which can be bound to a given REST client with a simple annotation.
For more information, see the Quarkus xref:security-openid-connect-client-reference.adoc#token-propagation-reactive[Access token propagation] guide.
For more information, see the Quarkus xref:security-openid-connect-client-reference.adoc#token-propagation-rest[Access token propagation] guide.

For example, after you have configured the <<google>> provider, you can have events added to the user's Google Calendar by using a REST client as shown in the following example:

Expand Down
35 changes: 29 additions & 6 deletions docs/src/main/asciidoc/tls-registry-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
////
[id="tls-registry-reference"]
= TLS registry reference
include::_attributes.adoc[]
:categories: network
:categories: web
:summary: TLS registry configuration and usage
:numbered:
:sectnums:
Expand Down Expand Up @@ -559,7 +560,7 @@ The `reload` method returns a `boolean` indicating whether the reload was succes
A value of `true` means the reload operation was successful, not necessarily that there were updates to the certificates.

After a `TlsConfiguration` has been reloaded, servers and clients using this configuration may need to perform specific actions to apply the new certificates.
The recommended approach is to fire a CDI event (`CertificateReloadedEvent`) that servers and clients can listen to and make the necessary changes:
The recommended approach is to fire a CDI event (`CertificateUpdatedEvent`) that servers and clients can listen to and make the necessary changes:

[source, java]
----
Expand All @@ -569,12 +570,12 @@ TlsConfigurationRegistry registry;
public void reload() {
TlsConfiguration config = registry.get("name").orElseThrow();
if (config.reload()) {
event.fire(new CertificateReloadedEvent("name", config));
event.fire(new CertificateUpdatedEvent("name", config));
}
}
// In the server or client code
public void onReload(@Observes CertificateReloadedEvent event) {
public void onReload(@Observes CertificateUpdatedEvent event) {
if ("name".equals(event.getName())) {
server.updateSSLOptions(event.tlsConfiguration().getSSLOptions());
// Or update the SSLContext.
Expand All @@ -588,7 +589,7 @@ These APIs provide a way to implement custom certificate reloading.

The TLS registry includes a built-in mechanism for periodically checking the file system for changes and reloading certificates.
You can configure periodic certificate reloading by using properties.
The `reload-period` property specifies the interval for reloading certificates and will emit a `CertificateReloadedEvent` each time certificates are reloaded.
The `reload-period` property specifies the interval for reloading certificates and will emit a `CertificateUpdatedEvent` each time certificates are reloaded.

[source, properties]
----
Expand All @@ -606,7 +607,7 @@ quarkus.tls.http.key-store.pem.0.cert=tls.crt
quarkus.tls.http.key-store.pem.0.key=tls.key
----

Remember that the impacted server and client may need to listen to the `CertificateReloadedEvent` to apply the new certificates.
Remember that the impacted server and client may need to listen to the `CertificateUpdatedEvent` to apply the new certificates.
This is automatically done for the Quarkus HTTP server, including the management interface if it is enabled.

== Using Kubernetes secrets or cert-manager
Expand Down Expand Up @@ -1180,6 +1181,27 @@ quarkus.tls.lets-encrypt.enabled=true
quarkus.management.enabled=true
----

[IMPORTANT]
====
.Port 80
The Let's Encrypt ACME challenge requires that the application is reachable on port `80` (basically: `http://your-dns-name`).
Ensure the port `80` is accessible from the Internet.
It might require an explicit security policy depending on your hosting provider.
We also recommend setting `quarkus.http.insecure-requests` to `redirect` to redirect all HTTP requests to HTTPS.
The ACME challenge accepts self-signed certificates and up to 10 redirections:
[source, properties]
----
quarkus.tls.lets-encrypt.enabled=true
quarkus.management.enabled=true
quarkus.http.insecure-requests=redirect
----
====

[[lets-encrypt-prepare]]

The challenge is served from the primary HTTP interface (accessible from your DNS domain name).

IMPORTANT: Do not start your application yet.
Expand Down Expand Up @@ -1305,5 +1327,6 @@ Now, because ngrok only forwards ACME challenges over HTTP, start ngrok as follo
ngrok http --domain <YOUR-NGROK-DOMAIN> 8080 --scheme http <1>
----
<1> `8080` is the localhost HTTP port your application is listening on.
Note that the application will be accessible from `http://YOUR-NGROK-DOMAIN` on port `80` but redirected to your local machine on port `8080`.

You can now test the Quarkus Let's Encrypt ACME feature from your local machine.
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveFieldBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveMethodBuildItem;
import io.quarkus.deployment.builditem.nativeimage.RuntimeReinitializedClassBuildItem;
import io.quarkus.deployment.logging.LogCleanupFilterBuildItem;
import io.quarkus.deployment.pkg.steps.NativeOrNativeSourcesBuild;
import io.quarkus.deployment.recording.RecorderContext;
Expand Down Expand Up @@ -594,6 +595,12 @@ public void build(
hibernateValidatorBuildTimeConfig)));
}

@BuildStep
public RuntimeReinitializedClassBuildItem reinitClockProviderSystemTimezone() {
return new RuntimeReinitializedClassBuildItem(
"io.quarkus.hibernate.validator.runtime.clockprovider.HibernateValidatorClockProviderSystemZoneIdHolder");
}

@BuildStep
void indexAdditionalConstrainedClasses(List<AdditionalConstrainedClassBuildItem> additionalConstrainedClasses,
BuildProducer<AdditionalConstrainedClassesIndexBuildItem> additionalConstrainedClassesIndex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import io.quarkus.arc.runtime.BeanContainer;
import io.quarkus.arc.runtime.BeanContainerListener;
import io.quarkus.hibernate.validator.ValidatorFactoryCustomizer;
import io.quarkus.hibernate.validator.runtime.clockprovider.RuntimeReinitializedDefaultClockProvider;
import io.quarkus.hibernate.validator.runtime.jaxrs.ResteasyConfigSupport;
import io.quarkus.runtime.LocalesBuildTimeConfig;
import io.quarkus.runtime.ShutdownContext;
Expand Down Expand Up @@ -129,6 +130,11 @@ public void created(BeanContainer container) {
InstanceHandle<ClockProvider> configuredClockProvider = Arc.container().instance(ClockProvider.class);
if (configuredClockProvider.isAvailable()) {
configuration.clockProvider(configuredClockProvider.get());
} else {
// If user didn't provide a custom clock provider we want to set our own.
// This provider ensure the correct behavior in a native mode as it does not
// cache the time zone at a build time.
configuration.clockProvider(RuntimeReinitializedDefaultClockProvider.INSTANCE);
}

// Hibernate Validator-specific configuration
Expand Down
Loading

0 comments on commit 245285f

Please sign in to comment.