Skip to content

Commit

Permalink
Merge pull request #46283 from gsmet/3.19.0-backports-1
Browse files Browse the repository at this point in the history
[3.19] 3.19.0 backports 1
  • Loading branch information
gsmet authored Feb 15, 2025
2 parents aa433ad + ab23341 commit e380631
Show file tree
Hide file tree
Showing 77 changed files with 3,827 additions and 127 deletions.
2 changes: 1 addition & 1 deletion bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
<h2.version>2.3.230</h2.version> <!-- When updating, needs to be matched in io.quarkus.hibernate.orm.runtime.config.DialectVersions
and the dependency jts-core needs to be updated in extensions/jdbc/jdbc-h2/runtime/pom.xml -->
<postgresql-jdbc.version>42.7.5</postgresql-jdbc.version>
<mariadb-jdbc.version>3.4.1</mariadb-jdbc.version>
<mariadb-jdbc.version>3.5.2</mariadb-jdbc.version>
<mysql-jdbc.version>8.3.0</mysql-jdbc.version>
<mssql-jdbc.version>12.8.1.jre11</mssql-jdbc.version>
<adal4j.version>1.6.7</adal4j.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,16 @@ public interface TestConfig {
@WithDefault("false")
boolean enableCallbacksForIntegrationTests();

/**
* Used to override the artifact type against which a {@code @QuarkusIntegrationTest} or {@code @QuarkusMainIntegrationTest}
* run.
* For example, if the application's artifact is a container build from a jar, this property could be used to test the jar
* instead of the container.
* <p>
* Allowed values are: jar, native
*/
Optional<String> integrationTestArtifactType();

interface Profile {
/**
* A comma separated list of profiles (dev, test, prod or custom profiles) to use when testing using @QuarkusTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,20 @@ public class ContainerImages {
public static final String UBI9_MINIMAL_VERSION = UBI9_VERSION;
public static final String UBI9_MINIMAL = UBI9_MINIMAL_IMAGE_NAME + ":" + UBI9_MINIMAL_VERSION;

// Quarkus Micro image - https://quay.io/repository/quarkus/quarkus-micro-image?tab=tags
public static final String QUARKUS_MICRO_IMAGE_NAME = "quay.io/quarkus/quarkus-micro-image";
public static final String QUARKUS_MICRO_VERSION = "2.0";
public static final String QUARKUS_MICRO_IMAGE = QUARKUS_MICRO_IMAGE_NAME + ":" + QUARKUS_MICRO_VERSION;
// UBI 8 Quarkus Micro image - https://quay.io/repository/quarkus/quarkus-micro-image?tab=tags
public static final String UBI8_QUARKUS_MICRO_IMAGE_NAME = "quay.io/quarkus/quarkus-micro-image";
public static final String UBI8_QUARKUS_MICRO_VERSION = "2.0";
public static final String UBI8_QUARKUS_MICRO_IMAGE = UBI8_QUARKUS_MICRO_IMAGE_NAME + ":" + UBI8_QUARKUS_MICRO_VERSION;

// UBI 9 Quarkus Micro image - https://quay.io/repository/quarkus/ubi9-quarkus-micro-image?tab=tags
public static final String UBI9_QUARKUS_MICRO_IMAGE_NAME = "quay.io/quarkus/ubi9-quarkus-micro-image";
public static final String UBI9_QUARKUS_MICRO_VERSION = "2.0";
public static final String UBI9_QUARKUS_MICRO_IMAGE = UBI9_QUARKUS_MICRO_IMAGE_NAME + ":" + UBI9_QUARKUS_MICRO_VERSION;

// default Quarkus Micro image - https://quay.io/repository/quarkus/quarkus-micro-image?tab=tags
public static final String QUARKUS_MICRO_IMAGE_NAME = UBI9_QUARKUS_MICRO_IMAGE_NAME;
public static final String QUARKUS_MICRO_VERSION = UBI9_QUARKUS_MICRO_VERSION;
public static final String QUARKUS_MICRO_IMAGE = UBI9_QUARKUS_MICRO_IMAGE;

// === Runtime images for containers (JVM)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,7 @@ public AugmentResult createProductionApplication() {
if (artifactResultBuildItems.isEmpty()) {
throw new IllegalStateException("No artifact results were produced");
}
ArtifactResultBuildItem lastResult = artifactResultBuildItems.get(artifactResultBuildItems.size() - 1);
writeArtifactResultMetadataFile(buildSystemTargetBuildItem, lastResult);
writeArtifactResultMetadataFile(buildSystemTargetBuildItem, artifactResultBuildItems);

return new AugmentResult(artifactResultBuildItems.stream()
.map(a -> new ArtifactResult(a.getPath(), a.getType(), a.getMetadata()))
Expand Down Expand Up @@ -241,14 +240,28 @@ private void writeDebugSourceFile(BuildResult result) {
}

private void writeArtifactResultMetadataFile(BuildSystemTargetBuildItem outputTargetBuildItem,
ArtifactResultBuildItem lastResult) {
List<ArtifactResultBuildItem> artifactResultBuildItems) {
ArtifactResultBuildItem lastArtifact = artifactResultBuildItems.get(artifactResultBuildItems.size() - 1);
Path quarkusArtifactMetadataPath = outputTargetBuildItem.getOutputDirectory().resolve("quarkus-artifact.properties");
Properties properties = new Properties();
properties.put("type", lastResult.getType());
if (lastResult.getPath() != null) {
properties.put("path", outputTargetBuildItem.getOutputDirectory().relativize(lastResult.getPath()).toString());
properties.put("type", lastArtifact.getType());
if (lastArtifact.getPath() != null) {
properties.put("path", artifactPathForResultMetadata(outputTargetBuildItem, lastArtifact));
} else {
if (lastArtifact.getType().endsWith("-container")) {
// in this case we write "path" as to contain the path to the artifact from which the container was built
try {
ArtifactResultBuildItem baseArtifact = artifactResultBuildItems.get(artifactResultBuildItems.size() - 2);
if (baseArtifact.getPath() != null) {
properties.put("path", artifactPathForResultMetadata(outputTargetBuildItem, baseArtifact));
}
} catch (IndexOutOfBoundsException e) {
// this should never happen really as a container is always built from some other artifact
log.debug(e);
}
}
}
Map<String, String> metadata = lastResult.getMetadata();
Map<String, String> metadata = lastArtifact.getMetadata();
if (metadata != null) {
for (Map.Entry<String, String> entry : metadata.entrySet()) {
properties.put("metadata." + entry.getKey(), entry.getValue());
Expand All @@ -261,6 +274,11 @@ private void writeArtifactResultMetadataFile(BuildSystemTargetBuildItem outputTa
}
}

private static String artifactPathForResultMetadata(BuildSystemTargetBuildItem outputTargetBuildItem,
ArtifactResultBuildItem artifactResultBuildItem) {
return outputTargetBuildItem.getOutputDirectory().relativize(artifactResultBuildItem.getPath()).toString();
}

@Override
public StartupActionImpl createInitialRuntimeApplication() {
if (launchMode == LaunchMode.NORMAL) {
Expand Down
5 changes: 5 additions & 0 deletions docs/src/main/asciidoc/amqp-dev-services.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,8 @@ quarkus.amqp.devservices.image-name=quay.io/artemiscloud/activemq-artemis-broker
IMPORTANT: The configured image must be _compatible_ with the `activemq-artemis-broker` one.
The container is launched with the `AMQ_USER`, `AMQ_PASSWORD` and `AMQ_EXTRA_ARGS` environment variables.
The ports 5672 and 8161 (web console) are exposed.

[[configuration-reference-devservices]]
== Configuration reference

include::{generated-dir}/config/quarkus-messaging-amqp_quarkus.amqp.devservices.adoc[opts=optional, leveloffset=+1]
10 changes: 5 additions & 5 deletions docs/src/main/asciidoc/infinispan-dev-services.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,11 @@ Quarkus supports a feature called Dev Services that allows you to create various
If you have docker running and have not configured `quarkus.infinispan-client.hosts`,
Quarkus will automatically start an Infinispan container when running tests or dev mode, and automatically configure the connection.

The following properties are available to customize the Infinispan Dev Services:

include::{generated-dir}/config/quarkus-infinispan-client_quarkus.infinispan-client.devservices.adoc[opts=optional, leveloffset=+1]

When running the production version of the application, the Infinispan connection need to be configured as normal,
so if you want to include a production database config in your `application.properties` and continue to use Dev Services
we recommend that you use the `%prod.` profile to define your Infinispan settings.

Dev Services for Infinispan relies on Docker to start the server.
Dev Services for Infinispan relies on Docker/Podman to start the server.

== Connecting to the running Infinispan Server

Expand Down Expand Up @@ -207,3 +203,7 @@ The default service name is `infinispan`.

Sharing is enabled by default in dev mode, but disabled in test mode.
You can disable the sharing with `quarkus.infinispan-client.devservices.shared=false`

== Configuration reference

include::{generated-dir}/config/quarkus-infinispan-client_quarkus.infinispan-client.devservices.adoc[opts=optional, leveloffset=+1]
5 changes: 5 additions & 0 deletions docs/src/main/asciidoc/kafka-dev-services.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,8 @@ quarkus.kafka.devservices.redpanda.transaction-enabled=false
----

NOTE: Redpanda transactions does not support exactly-once processing.

[[configuration-reference-devservices]]
== Configuration reference

include::{generated-dir}/config/quarkus-kafka-client_quarkus.kafka.devservices.adoc[opts=optional, leveloffset=+1]
4 changes: 4 additions & 0 deletions docs/src/main/asciidoc/kubernetes-dev-services.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,7 @@ quarkus.kubernetes-client.devservices.api-version=1.22
`api-only` only starts a Kubernetes API Server. If you need a fully-featured Kubernetes cluster that can spin up Pods, you can use `k3s` or `kind`. Note that they both requires to run in Docker privileged mode.

If `api-version` is not set, the latest version for the given flavor will be used. Otherwise, the version must match a https://github.com/dajudge/kindcontainer/blob/master/k8s-versions.json[version supported by the given flavor].

== Configuration reference

include::{generated-dir}/config/quarkus-kubernetes-client_quarkus.kubernetes-client.devservices.adoc[opts=optional, leveloffset=+1]
4 changes: 4 additions & 0 deletions docs/src/main/asciidoc/mongodb-dev-services.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,7 @@ The default service name is `mongodb`.

Sharing is enabled by default in dev mode, but disabled in test mode.
You can disable the sharing with `quarkus.mongodb.devservices.shared=false`.

== Configuration reference

include::{generated-dir}/config/quarkus-mongodb-client_quarkus.mongodb.devservices.adoc[opts=optional, leveloffset=+1]
5 changes: 5 additions & 0 deletions docs/src/main/asciidoc/pulsar-dev-services.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,8 @@ The following example enables transaction support:
quarkus.pulsar.devservices.broker-config.transaction-coordinator-enabled=true
quarkus.pulsar.devservices.broker-config.system-topic-enabled=true
----

[[configuration-reference-devservices]]
== Configuration reference

include::{generated-dir}/config/quarkus-messaging-pulsar_quarkus.pulsar.devservices.adoc[opts=optional, leveloffset=+1]
4 changes: 2 additions & 2 deletions docs/src/main/asciidoc/quarkus-runtime-base-image.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ include::_attributes.adoc[]
:topics: docker,podman,images

To ease the containerization of native executables, Quarkus provides a base image providing the requirements to run these executables.
The `quarkus-micro-image:2.0` image is:
The `ubi9-quarkus-micro-image:2.0` image is:

* small (based on `ubi8-micro`)
* small (based on `ubi9-micro`)
* designed for containers
* contains the right set of dependencies (glibc, libstdc++, zlib)
* support upx-compressed executables (more details on the xref:upx.adoc[enabling compression documentation])
Expand Down
5 changes: 5 additions & 0 deletions docs/src/main/asciidoc/rabbitmq-dev-services.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,8 @@ Additionally, any additional arguments can be provided to the binding's definiti
----
quarkus.rabbitmq.devservices.bindings.a-binding.arguments.non-std-option=value
----

[[configuration-reference-devservices]]
== Configuration reference

include::{generated-dir}/config/quarkus-messaging-rabbitmq_quarkus.rabbitmq.devservices.adoc[opts=optional, leveloffset=+1]
8 changes: 4 additions & 4 deletions docs/src/main/asciidoc/redis-dev-services.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ Quarkus supports a feature called Dev Services that allows you to create various
What that means practically, is that if you have docker running and have not configured `quarkus.redis.hosts`,
Quarkus will automatically start a Redis container when running tests or dev mode, and automatically configure the connection.

Available properties to customize the Redis Dev Service.

include::{generated-dir}/config/quarkus-redis-client_quarkus.redis.devservices.adoc[opts=optional, leveloffset=+1]

When running the production version of the application, the Redis connection need to be configured as normal,
so if you want to include a production database config in your `application.properties` and continue to use Dev Services
we recommend that you use the `%prod.` profile to define your Redis settings.
Expand All @@ -41,3 +37,7 @@ The default service name is `redis`.

Sharing is enabled by default in dev mode, but disabled in test mode.
You can disable the sharing with `quarkus.redis.devservices.shared=false`.

== Configuration reference

include::{generated-dir}/config/quarkus-redis-client_quarkus.redis.devservices.adoc[opts=optional, leveloffset=+1]
Original file line number Diff line number Diff line change
Expand Up @@ -1309,7 +1309,30 @@ If you set `quarkus.oidc.client-id`, but your endpoint does not require remote a
Quarkus `web-app` applications always require the `quarkus.oidc.client-id` property.
====

== Mutual TLS token binding
== Sender-constraining access tokens

=== Demonstrating Proof of Possession (DPoP)

https://datatracker.ietf.org/doc/html/rfc9449[RFC9449] describes a Demonstrating Proof of Possession (DPoP) mechanism for cryprographically binding an access token to the current client, preventing the access token loss and replay.

Single page application (SPA) public clients generate DPoP proof tokens and use them to acquire and submit access tokens which are cryptograhically bound to DPoP proofs.

Enabling DPoP support in Quarkus requires a single property.

For example:

[source,properties]
----
quarkus.oidc.auth-server-url=${your_oidc_provider_url}
quarkus.oidc.token.authorization-scheme=dpop <1>
----
<1> Require that the access tokens are provided using HTTP `Authorization DPoP` scheme value.

After accepting such tokens, Quarkus will go through the full https://datatracker.ietf.org/doc/html/rfc9449#name-checking-dpop-proofs[DPoP token verification process].

Support for custom DPoP nonce providers may be offered in the future.

=== Mutual TLS token binding

https://datatracker.ietf.org/doc/html/rfc8705[RFC8705] describes a mechanism for binding access tokens to Mutual TLS (mTLS) client authentication certificates.
It requires that a client certificate's SHA256 thumbprint matches a JWT token or token introspection confirmation `x5t#S256` certificate thumbprint.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@ image::dev-ui-oidc-dev-svc-login-for-custom-users.png[alt=Dev Services for OIDC

Whichever user you choose, no password is required.

== Configuration reference

include::{generated-dir}/config/quarkus-devservices-keycloak_quarkus.keycloak.adoc[opts=optional, leveloffset=+1]

== References

* xref:dev-ui.adoc[Dev UI]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;

import io.quarkus.runtime.annotations.ConfigDocMapKey;
import io.quarkus.runtime.annotations.ConfigRoot;
Expand Down Expand Up @@ -120,6 +121,14 @@ public interface KeycloakDevServicesConfig {
*/
Optional<String> startCommand();

/**
* Keycloak features.
* Use this property to enable one or more experimental Keycloak features.
* Note, if you also have to customize a Keycloak {@link #startCommand()}, you can use
* a `--features` option as part of the start command sequence, instead of configuring this property.
*/
Optional<Set<String>> features();

/**
* The name of the Keycloak realm.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ private static RunningDevService startContainer(
capturedDevServicesConfiguration.shared(),
capturedDevServicesConfiguration.javaOpts(),
capturedDevServicesConfiguration.startCommand(),
capturedDevServicesConfiguration.features(),
capturedDevServicesConfiguration.showLogs(),
capturedDevServicesConfiguration.containerMemoryLimit(),
errors);
Expand Down Expand Up @@ -485,14 +486,15 @@ private static class QuarkusOidcContainer extends GenericContainer<QuarkusOidcCo
private final boolean keycloakX;
private final List<RealmRepresentation> realmReps = new LinkedList<>();
private final Optional<String> startCommand;
private final Optional<Set<String>> features;
private final boolean showLogs;
private final MemorySize containerMemoryLimit;
private final List<String> errors;

public QuarkusOidcContainer(DockerImageName dockerImageName, OptionalInt fixedExposedPort, boolean useSharedNetwork,
List<String> realmPaths, Map<String, String> resources, String containerLabelValue,
boolean sharedContainer, Optional<String> javaOpts, Optional<String> startCommand, boolean showLogs,
MemorySize containerMemoryLimit, List<String> errors) {
boolean sharedContainer, Optional<String> javaOpts, Optional<String> startCommand,
Optional<Set<String>> features, boolean showLogs, MemorySize containerMemoryLimit, List<String> errors) {
super(dockerImageName);

this.useSharedNetwork = useSharedNetwork;
Expand All @@ -512,6 +514,7 @@ public QuarkusOidcContainer(DockerImageName dockerImageName, OptionalInt fixedEx

this.fixedExposedPort = fixedExposedPort;
this.startCommand = startCommand;
this.features = features;
this.showLogs = showLogs;
this.containerMemoryLimit = containerMemoryLimit;
this.errors = errors;
Expand Down Expand Up @@ -554,8 +557,12 @@ protected void configure() {
if (keycloakX) {
addEnv(KEYCLOAK_QUARKUS_ADMIN_PROP, KEYCLOAK_ADMIN_USER);
addEnv(KEYCLOAK_QUARKUS_ADMIN_PASSWORD_PROP, KEYCLOAK_ADMIN_PASSWORD);
withCommand(startCommand.orElse(KEYCLOAK_QUARKUS_START_CMD)
+ (useSharedNetwork ? " --hostname-backchannel-dynamic true" : ""));
String finalStartCommand = startCommand.orElse(KEYCLOAK_QUARKUS_START_CMD)
+ (useSharedNetwork ? " --hostname-backchannel-dynamic true" : "");
if (features.isPresent()) {
finalStartCommand += (" --features=" + features.get().stream().collect(Collectors.joining(",")));
}
withCommand(finalStartCommand);
addUpConfigResource();
if (isHttps()) {
addExposedPort(KEYCLOAK_HTTPS_PORT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -664,9 +664,38 @@ interface HibernateOrmConfigPersistenceValidation {

/**
* Enables the Bean Validation integration.
*
* @deprecated Use {@link #mode()} instead.
*/
@Deprecated(since = "3.19", forRemoval = true)
@WithDefault("true")
boolean enabled();

/**
* Defines how the Bean Validation integration behaves.
*/
@WithDefault("auto")
Set<ValidationMode> mode();

enum ValidationMode {
/**
* If a Bean Validation provider is present then behaves as if both {@link ValidationMode#CALLBACK} and
* {@link ValidationMode#DDL} modes are configured. Otherwise, same as {@link ValidationMode#NONE}.
*/
AUTO,
/**
* Bean Validation will perform the lifecycle event validation.
*/
CALLBACK,
/**
* Bean Validation constraints will be considered for the DDL operations.
*/
DDL,
/**
* Bean Validation integration will be disabled.
*/
NONE
}
}

}
Loading

0 comments on commit e380631

Please sign in to comment.