diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index 52a87a02356fc..d6809b2101257 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -172,7 +172,7 @@
0.3.04.14.06.1.SP2
- 3.2.SP1
+ 3.2.SP26.23.25.12.0
diff --git a/docs/src/main/asciidoc/http-reference.adoc b/docs/src/main/asciidoc/http-reference.adoc
index 396f2e571acda..b7f9786b4db77 100644
--- a/docs/src/main/asciidoc/http-reference.adoc
+++ b/docs/src/main/asciidoc/http-reference.adoc
@@ -421,6 +421,7 @@ include::{generated-dir}/config/quarkus-vertx-http-config-group-access-log-confi
|First line of the request | `%r` | `%{REQUEST_LINE}`
|HTTP status code of the response | `%s` | `%{RESPONSE_CODE}`
|Date and time, in Common Log Format format | `%t` | `%{DATE_TIME}`
+|Date and time as defined by a DateTimeFormatter compliant string | | `%{time,date_fime_formatter_string}`
|Remote user that was authenticated | `%u` | `%{REMOTE_USER}`
|Requested URL path | `%U` | `%{REQUEST_URL}`
|Request relative path | `%R` | `%{REQUEST_PATH}`
diff --git a/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc b/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc
index c0bc3c54661dc..63d99eab3b2fc 100644
--- a/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc
+++ b/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc
@@ -183,6 +183,15 @@ Finally, the `quarkus.http.auth.permission.authenticated` permission is set to t
In this case, all paths are protected by a policy that ensures only `authenticated` users can access them.
For more information, see xref:security-authorize-web-endpoints-reference.adoc[Security Authorization Guide].
+[NOTE]
+====
+When you do not configure a client secret with `quarkus.oidc.credentials.secret`, it is recommended to configure `quarkus.oidc.token-state-manager.encryption-secret`.
+
+The `quarkus.oidc.token-state-manager.encryption-secret` enables the default token state manager to encrypt the user tokens in a browser cookie. If this key is not defined, and the `quarkus.oidc.credentials.secret` fallback is not configured, Quarkus uses a random key. A random key causes existing logins to be invalidated either on application restart or in environment with multiple instances of your application. Alternatively, encryption can also be disabled by setting `quarkus.oidc.token-state-manager.encryption-required` to `false`. However, you should disable secret encryption in development environments only.
+
+The encryption secret is recommended to be 32 chars long. For example, `quarkus.oidc.token-state-manager.encryption-secret=AyM1SysPpbyDfgZld3umj1qzKObwVMk`
+====
+
== Start and configure the Keycloak server
To start a Keycloak server, use Docker and run the following command:
diff --git a/docs/src/main/asciidoc/tls-registry-reference.adoc b/docs/src/main/asciidoc/tls-registry-reference.adoc
index 4b2198da13ebc..3c918ee0b26a8 100644
--- a/docs/src/main/asciidoc/tls-registry-reference.adoc
+++ b/docs/src/main/asciidoc/tls-registry-reference.adoc
@@ -518,4 +518,4 @@ When the application starts, the TLS registry performs some checks to ensure the
- the cipher suites and protocols are valid
- the CRLs are valid
-If any of these checks fail, the application will fail to start.
\ No newline at end of file
+If any of these checks fail, the application will fail to start.
diff --git a/docs/src/main/asciidoc/websockets-next-reference.adoc b/docs/src/main/asciidoc/websockets-next-reference.adoc
index 11e14ba18a2c4..4b93f261aa4eb 100644
--- a/docs/src/main/asciidoc/websockets-next-reference.adoc
+++ b/docs/src/main/asciidoc/websockets-next-reference.adoc
@@ -610,12 +610,28 @@ Item find(Item item) {
1. Specify the codec to use for both the deserialization of the incoming message
2. Specify the codec to use for the serialization of the outgoing message
-== Handle Pong message
+== Ping/pong messages
-The `@OnPongMessage` annotation is used to consume pong messages.
-A websocket endpoint must declare at most one method annotated with `@OnPongMessage`.
+A https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.2[ping message] may serve as a keepalive or to verify the remote endpoint.
+A https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.3[pong message] is sent in response to a ping message and it must have an identical payload.
-The method must accept a single parameter of type `Buffer`:
+The server automatically responds to a ping message sent from the client.
+In other words, there is no need for `@OnPingMessage` callback declared on an endpoint.
+
+The server can send ping messages to a connected client.
+The `WebSocketConnection` declares methods to send ping messages; there is a non-blocking variant: `WebSocketConnection#sendPing(Buffer)` and a blocking variant: `WebSocketConnection#sendPingAndAwait(Buffer)`.
+By default, the ping messages are not sent automatically.
+However, the configuration property `quarkus.websockets-next.server.auto-ping-interval` can be used to set the interval after which, the server sends a ping message to a connected client automatically.
+
+[source,properties]
+----
+quarkus.websockets-next.server.auto-ping-interval=2 <1>
+----
+<1> Sends a ping message to a connected client every 2 seconds.
+
+The `@OnPongMessage` annotation is used to define a callback that consumes pong messages sent from the client.
+An endpoint must declare at most one method annotated with `@OnPongMessage`.
+The callback method must return either `void` or `Uni`, and it must accept a single parameter of type `Buffer`.
[source,java]
----
@@ -625,6 +641,8 @@ void pong(Buffer data) {
}
----
+NOTE: The server can also send unsolicited pong messages that may serve as a unidirectional heartbeat. There is a non-blocking variant: `WebSocketConnection#sendPong(Buffer)` and also a blocking variant: `WebSocketConnection#sendPongAndAwait(Buffer)`.
+
[[websocket-next-security]]
== Security
diff --git a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmConfigPersistenceUnit.java b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmConfigPersistenceUnit.java
index 1f29cbd83ca83..94fe4d3b64c94 100644
--- a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmConfigPersistenceUnit.java
+++ b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmConfigPersistenceUnit.java
@@ -47,10 +47,10 @@ public interface HibernateOrmConfigPersistenceUnit {
// @formatter:off
/**
- * Path to a file containing the SQL statements to execute when Hibernate ORM starts.
+ * Paths to files containing the SQL statements to execute when Hibernate ORM starts.
*
- * The file is retrieved from the classpath resources,
- * so it must be located in the resources directory (e.g. `src/main/resources`).
+ * The files are retrieved from the classpath resources,
+ * so they must be located in the resources directory (e.g. `src/main/resources`).
*
* The default value for this setting differs depending on the Quarkus launch mode:
*
@@ -82,7 +82,7 @@ public interface HibernateOrmConfigPersistenceUnit {
* @asciidoclet
*/
// @formatter:on
- @ConfigDocDefault("import.sql in DEV, TEST ; no-file otherwise")
+ @ConfigDocDefault("import.sql in dev and test modes ; no-file otherwise")
Optional> sqlLoadScript();
/**
diff --git a/extensions/kafka-client/deployment/src/main/java/io/quarkus/kafka/client/deployment/KafkaProcessor.java b/extensions/kafka-client/deployment/src/main/java/io/quarkus/kafka/client/deployment/KafkaProcessor.java
index 41f3415a761c6..295c223570ee9 100644
--- a/extensions/kafka-client/deployment/src/main/java/io/quarkus/kafka/client/deployment/KafkaProcessor.java
+++ b/extensions/kafka-client/deployment/src/main/java/io/quarkus/kafka/client/deployment/KafkaProcessor.java
@@ -222,6 +222,7 @@ public void build(
BuildProducer sslNativeSupport) {
final Set toRegister = new HashSet<>();
+ nativeLibs.produce(new NativeImageResourceBuildItem("kafka/kafka-version.properties"));
collectImplementors(toRegister, indexBuildItem, Serializer.class);
collectImplementors(toRegister, indexBuildItem, Deserializer.class);
collectImplementors(toRegister, indexBuildItem, Partitioner.class);
diff --git a/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientConfig.java b/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientConfig.java
index 71c1ba1be8d2d..9267e5bc9fe31 100644
--- a/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientConfig.java
+++ b/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientConfig.java
@@ -42,6 +42,7 @@ public class RestClientConfig {
EMPTY.keyStorePassword = Optional.empty();
EMPTY.keyStoreType = Optional.empty();
EMPTY.hostnameVerifier = Optional.empty();
+ EMPTY.tlsConfigurationName = Optional.empty();
EMPTY.connectionTTL = Optional.empty();
EMPTY.connectionPoolSize = Optional.empty();
EMPTY.keepAliveEnabled = Optional.empty();
@@ -201,6 +202,20 @@ public class RestClientConfig {
@ConfigItem
public Optional hostnameVerifier;
+ /**
+ * The name of the TLS configuration to use.
+ *
+ * If not set and the default TLS configuration is configured ({@code quarkus.tls.*}) then that will be used.
+ * If a name is configured, it uses the configuration from {@code quarkus.tls..*}
+ * If a name is configured, but no TLS configuration is found with that name then an error will be thrown.
+ *
+ * If no TLS configuration is set, then the keys-tore, trust-store, etc. properties will be used.
+ *
+ * This property is not applicable to the RESTEasy Client.
+ */
+ @ConfigItem
+ public Optional tlsConfigurationName;
+
/**
* The time in ms for which a connection remains unused in the connection pool before being evicted and closed.
* A timeout of {@code 0} means there is no timeout.
@@ -317,6 +332,7 @@ public static RestClientConfig load(String configKey) {
instance.keyStorePassword = getConfigValue(configKey, "key-store-password", String.class);
instance.keyStoreType = getConfigValue(configKey, "key-store-type", String.class);
instance.hostnameVerifier = getConfigValue(configKey, "hostname-verifier", String.class);
+ instance.tlsConfigurationName = getConfigValue(configKey, "tls-configuration-name", String.class);
instance.connectionTTL = getConfigValue(configKey, "connection-ttl", Integer.class);
instance.connectionPoolSize = getConfigValue(configKey, "connection-pool-size", Integer.class);
instance.keepAliveEnabled = getConfigValue(configKey, "keep-alive-enabled", Boolean.class);
@@ -358,6 +374,7 @@ public static RestClientConfig load(Class> interfaceClass) {
instance.keyStorePassword = getConfigValue(interfaceClass, "key-store-password", String.class);
instance.keyStoreType = getConfigValue(interfaceClass, "key-store-type", String.class);
instance.hostnameVerifier = getConfigValue(interfaceClass, "hostname-verifier", String.class);
+ instance.tlsConfigurationName = getConfigValue(interfaceClass, "tls-configuration-name", String.class);
instance.connectionTTL = getConfigValue(interfaceClass, "connection-ttl", Integer.class);
instance.connectionPoolSize = getConfigValue(interfaceClass, "connection-pool-size", Integer.class);
instance.keepAliveEnabled = getConfigValue(interfaceClass, "keep-alive-enabled", Boolean.class);
diff --git a/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientFallbackConfigSourceInterceptor.java b/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientFallbackConfigSourceInterceptor.java
index a30fe54566ebf..84507edb3cb36 100644
--- a/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientFallbackConfigSourceInterceptor.java
+++ b/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientFallbackConfigSourceInterceptor.java
@@ -38,6 +38,7 @@ public class RestClientFallbackConfigSourceInterceptor extends FallbackConfigSou
CLIENT_PROPERTIES.put("key-store", "keyStore");
CLIENT_PROPERTIES.put("key-store-password", "keyStorePassword");
CLIENT_PROPERTIES.put("key-store-type", "keyStoreType");
+ CLIENT_PROPERTIES.put("tls-configuration-name", "tlsConfigurationName");
CLIENT_PROPERTIES.put("follow-redirects", "followRedirects");
CLIENT_PROPERTIES.put("proxy-address", "proxyAddress");
CLIENT_PROPERTIES.put("query-param-style", "queryParamStyle");
diff --git a/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientsConfig.java b/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientsConfig.java
index b02e27baa1aa1..ab20ac8605a6b 100644
--- a/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientsConfig.java
+++ b/extensions/resteasy-classic/rest-client-config/runtime/src/main/java/io/quarkus/restclient/config/RestClientsConfig.java
@@ -278,6 +278,20 @@ public class RestClientsConfig {
@ConfigItem
public Optional keyStoreType;
+ /**
+ * The name of the TLS configuration to use.
+ *
+ * If not set and the default TLS configuration is configured ({@code quarkus.tls.*}) then that will be used.
+ * If a name is configured, it uses the configuration from {@code quarkus.tls..*}
+ * If a name is configured, but no TLS configuration is found with that name then an error will be thrown.
+ *
+ * If no TLS configuration is set, then the keys-tore, trust-store, etc. properties will be used.
+ *
Methods returning {@code void} are considered blocking and should be executed on a worker thread.
- *
Methods returning {@link io.smallrye.mutiny.Uni} or {@link io.smallrye.mutiny.Multi} are considered non-blocking and
- * should be executed on an event loop thread.
- *
Methods returning any other type are considered blocking and should be executed on a worker thread.
+ *
Methods returning {@code io.smallrye.mutiny.Uni} are considered non-blocking and should be executed on an event
+ * loop thread.
*
*
*
Method parameters
diff --git a/independent-projects/bootstrap/pom.xml b/independent-projects/bootstrap/pom.xml
index ae20107f0ddb6..4ea736e1b20c5 100644
--- a/independent-projects/bootstrap/pom.xml
+++ b/independent-projects/bootstrap/pom.xml
@@ -72,7 +72,7 @@
2.03.5.12.3.0
- 1.5.0
+ 1.5.28.80.0.100.1.3
diff --git a/independent-projects/extension-maven-plugin/pom.xml b/independent-projects/extension-maven-plugin/pom.xml
index d45da6dfe91fe..c1070b66a8c3c 100644
--- a/independent-projects/extension-maven-plugin/pom.xml
+++ b/independent-projects/extension-maven-plugin/pom.xml
@@ -39,7 +39,7 @@
113.9.72.17.1
- 1.5.0
+ 1.5.25.10.2
diff --git a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/TlsConfig.java b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/TlsConfig.java
new file mode 100644
index 0000000000000..1d85e98c0996f
--- /dev/null
+++ b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/TlsConfig.java
@@ -0,0 +1,80 @@
+package org.jboss.resteasy.reactive.client;
+
+import java.security.KeyStore;
+import java.util.Optional;
+
+import javax.net.ssl.SSLContext;
+
+import io.vertx.core.net.KeyCertOptions;
+import io.vertx.core.net.SSLOptions;
+import io.vertx.core.net.TrustOptions;
+
+public interface TlsConfig {
+
+ /**
+ * Returns the key store.
+ *
+ * @return the key store if configured.
+ */
+ KeyStore getKeyStore();
+
+ /**
+ * Returns the key store options.
+ *
+ * @return the key store options if configured.
+ */
+ KeyCertOptions getKeyStoreOptions();
+
+ /**
+ * Returns the trust store.
+ *
+ * @return the trust store if configured.
+ */
+ KeyStore getTrustStore();
+
+ /**
+ * Returns the trust store options.
+ *
+ * @return the trust store options if configured.
+ */
+ TrustOptions getTrustStoreOptions();
+
+ /**
+ * Returns the (Vert.x) SSL options.
+ *
+ * @return the {@link SSLOptions}, {@code null} if not configured.
+ */
+ SSLOptions getSSLOptions();
+
+ /**
+ * Creates and returns the SSL Context.
+ *
+ * @return the {@link SSLContext}, {@code null} if not configured.
+ * @throws Exception if the SSL Context cannot be created.
+ */
+ SSLContext createSSLContext() throws Exception;
+
+ /**
+ * Returns the hostname verification algorithm for this configuration.
+ * {@code "NONE"} means no hostname verification.
+ *
+ * @return the hostname verification algorithm.
+ */
+ Optional getHostnameVerificationAlgorithm();
+
+ /**
+ * Returns whether the key store is configured to use SNI.
+ * When SNI is used, the client indicate the server name during the TLS handshake, allowing the server to select the
+ * right certificate.
+ *
+ * @return {@code true} if the key store is configured to use SNI, {@code false} otherwise.
+ */
+ boolean usesSni();
+
+ /**
+ * Returns whether the trust store is configured to trust all certificates.
+ *
+ * @return {@code true} if the trust store is configured to trust all certificates, {@code false} otherwise.
+ */
+ boolean isTrustAll();
+}
diff --git a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientBuilderImpl.java b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientBuilderImpl.java
index 12e4381f7088d..8bfcc874f444c 100644
--- a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientBuilderImpl.java
+++ b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientBuilderImpl.java
@@ -27,6 +27,7 @@
import jakarta.ws.rs.ext.MessageBodyWriter;
import org.jboss.logging.Logger;
+import org.jboss.resteasy.reactive.client.TlsConfig;
import org.jboss.resteasy.reactive.client.api.ClientLogger;
import org.jboss.resteasy.reactive.client.api.LoggingScope;
import org.jboss.resteasy.reactive.client.interceptors.ClientGZIPDecodingInterceptor;
@@ -40,25 +41,17 @@
import io.vertx.core.http.HttpVersion;
import io.vertx.core.net.JksOptions;
import io.vertx.core.net.ProxyOptions;
+import io.vertx.core.net.SSLOptions;
public class ClientBuilderImpl extends ClientBuilder {
private static final Logger log = Logger.getLogger(ClientBuilderImpl.class);
private static final ClientContextResolver CLIENT_CONTEXT_RESOLVER = ClientContextResolver.getInstance();
- private static final char[] EMPTY_CHAR_ARARAY = new char[0];
+ private static final char[] EMPTY_CHAR_ARRAY = new char[0];
public static final String PIPE = Pattern.quote("|");
private ConfigurationImpl configuration;
- private HostnameVerifier hostnameVerifier;
- private KeyStore keyStore;
- private char[] keystorePassword;
- private SSLContext sslContext;
- private KeyStore trustStore;
- private char[] trustStorePassword;
- private boolean http2;
- private boolean alpn;
-
private String proxyHost;
private int proxyPort;
private String proxyPassword;
@@ -66,11 +59,23 @@ public class ClientBuilderImpl extends ClientBuilder {
private String nonProxyHosts;
private boolean followRedirects;
+
+ private boolean http2;
+ private boolean alpn;
+
+ // security settings
+ private KeyStore keyStore;
+ private char[] keystorePassword;
+ private KeyStore trustStore;
+ private char[] trustStorePassword;
private boolean trustAll;
private boolean verifyHost = true;
+ // overridden security settings
+ private TlsConfig tlsConfig;
private LoggingScope loggingScope;
private Integer loggingBodySize = 100;
+
private int maxChunkSize = 8096;
private MultiQueryParamMode multiQueryParamMode;
@@ -89,6 +94,11 @@ public ClientBuilder withConfig(Configuration config) {
return this;
}
+ public ClientBuilder tlsConfig(TlsConfig tlsConfig) {
+ this.tlsConfig = tlsConfig;
+ return this;
+ }
+
@Override
public ClientBuilder sslContext(SSLContext sslContext) {
// TODO
@@ -215,29 +225,10 @@ public ClientImpl build() {
options.setAlpnVersions(List.of(HttpVersion.HTTP_2, HttpVersion.HTTP_1_1));
}
- options.setVerifyHost(verifyHost);
- if (trustAll) {
- options.setTrustAll(true);
- options.setVerifyHost(false);
- }
-
- char[] effectiveTrustStorePassword = trustStorePassword == null ? EMPTY_CHAR_ARARAY : trustStorePassword;
- Buffer keyStore = asBuffer(this.keyStore, keystorePassword);
- Buffer trustStore = asBuffer(this.trustStore, effectiveTrustStorePassword);
- if (keyStore != null || trustStore != null) {
- options = options.setSsl(true);
- if (keyStore != null) {
- JksOptions jks = new JksOptions();
- jks.setValue(keyStore);
- jks.setPassword(new String(keystorePassword));
- options = options.setKeyStoreOptions(jks);
- }
- if (trustStore != null) {
- JksOptions jks = new JksOptions();
- jks.setValue(trustStore);
- jks.setPassword(new String(effectiveTrustStorePassword));
- options.setTrustStoreOptions(jks);
- }
+ if (tlsConfig != null) {
+ populateSecurityOptionsFromTlsConfig(options);
+ } else {
+ populateSecurityOptionsFromExplicitTlsProperties(options);
}
if (proxyHost != null) {
@@ -297,8 +288,8 @@ public ClientImpl build() {
return new ClientImpl(options,
configuration,
CLIENT_CONTEXT_RESOLVER.resolve(Thread.currentThread().getContextClassLoader()),
- hostnameVerifier,
- sslContext,
+ null,
+ null,
followRedirects,
multiQueryParamMode,
loggingScope,
@@ -306,6 +297,69 @@ public ClientImpl build() {
}
+ private void populateSecurityOptionsFromTlsConfig(HttpClientOptions options) {
+ options.setSsl(true);
+
+ if (tlsConfig.getTrustStoreOptions() != null) {
+ options.setTrustOptions(tlsConfig.getTrustStoreOptions());
+ }
+
+ // For mTLS:
+ if (tlsConfig.getKeyStoreOptions() != null) {
+ options.setKeyCertOptions(tlsConfig.getKeyStoreOptions());
+ }
+
+ if (tlsConfig.isTrustAll()) {
+ options.setTrustAll(true);
+ }
+ if (tlsConfig.getHostnameVerificationAlgorithm().isPresent()
+ && tlsConfig.getHostnameVerificationAlgorithm().get().equals("NONE")) {
+ // Only disable hostname verification if the algorithm is explicitly set to NONE
+ options.setVerifyHost(false);
+ }
+
+ SSLOptions sslOptions = tlsConfig.getSSLOptions();
+ if (sslOptions != null) {
+ options.setSslHandshakeTimeout(sslOptions.getSslHandshakeTimeout());
+ options.setSslHandshakeTimeoutUnit(sslOptions.getSslHandshakeTimeoutUnit());
+ for (String suite : sslOptions.getEnabledCipherSuites()) {
+ options.addEnabledCipherSuite(suite);
+ }
+ for (Buffer buffer : sslOptions.getCrlValues()) {
+ options.addCrlValue(buffer);
+ }
+ options.setEnabledSecureTransportProtocols(sslOptions.getEnabledSecureTransportProtocols());
+ options.setUseAlpn(sslOptions.isUseAlpn());
+ }
+ }
+
+ private void populateSecurityOptionsFromExplicitTlsProperties(HttpClientOptions options) {
+ options.setVerifyHost(verifyHost);
+ if (trustAll) {
+ options.setTrustAll(true);
+ options.setVerifyHost(false);
+ }
+
+ char[] effectiveTrustStorePassword = trustStorePassword == null ? EMPTY_CHAR_ARRAY : trustStorePassword;
+ Buffer keyStore = asBuffer(this.keyStore, keystorePassword);
+ Buffer trustStore = asBuffer(this.trustStore, effectiveTrustStorePassword);
+ if (keyStore != null || trustStore != null) {
+ options.setSsl(true);
+ if (keyStore != null) {
+ JksOptions jks = new JksOptions();
+ jks.setValue(keyStore);
+ jks.setPassword(new String(keystorePassword));
+ options.setKeyStoreOptions(jks);
+ }
+ if (trustStore != null) {
+ JksOptions jks = new JksOptions();
+ jks.setValue(trustStore);
+ jks.setPassword(new String(effectiveTrustStorePassword));
+ options.setTrustStoreOptions(jks);
+ }
+ }
+ }
+
private void configureNonProxyHosts(HttpClientOptions options, String nonProxyHosts) {
if (nonProxyHosts != null) {
for (String host : nonProxyHosts.split(PIPE)) {
diff --git a/independent-projects/tools/base-codestarts/src/main/resources/codestarts/quarkus/buildtool/maven/base/pom.tpl.qute.xml b/independent-projects/tools/base-codestarts/src/main/resources/codestarts/quarkus/buildtool/maven/base/pom.tpl.qute.xml
index 511b172afc41b..3d32afccb8efd 100644
--- a/independent-projects/tools/base-codestarts/src/main/resources/codestarts/quarkus/buildtool/maven/base/pom.tpl.qute.xml
+++ b/independent-projects/tools/base-codestarts/src/main/resources/codestarts/quarkus/buildtool/maven/base/pom.tpl.qute.xml
@@ -140,7 +140,7 @@
buildgenerate-codegenerate-code-tests
- {#if generate-native}
+ {#if generate-native and quarkus.platform.version.compareVersionTo("3.12") >= 0}
native-image-agent
{/if}
diff --git a/independent-projects/tools/base-codestarts/src/main/resources/codestarts/quarkus/project/quarkus/base/src/main/resources/META-INF/resources/index.tpl.qute.html b/independent-projects/tools/base-codestarts/src/main/resources/codestarts/quarkus/project/quarkus/base/src/main/resources/META-INF/resources/index.tpl.qute.html
new file mode 100644
index 0000000000000..4d248f14aaa89
--- /dev/null
+++ b/independent-projects/tools/base-codestarts/src/main/resources/codestarts/quarkus/project/quarkus/base/src/main/resources/META-INF/resources/index.tpl.qute.html
@@ -0,0 +1,288 @@
+{#if quarkus.platform.version.compareVersionTo("3.9") < 0}
+
+
+
+
+ {project.artifact-id} - {project.version}
+
+
+
+