Upgrade to Quarkus 3.13.2 (#31678)
* Upgrade to Quarkus 3.13.2 Closes #31676 Signed-off-by: Václav Muzikář <vmuzikar@redhat.com> Co-authored-by: Peter Zaoral <pzaoral@redhat.com> Co-authored-by: Martin Bartoš <mabartos@redhat.com>
This commit is contained in:
parent
e85f25434f
commit
cb418b0bfc
23 changed files with 146 additions and 52 deletions
|
@ -139,3 +139,11 @@ This endpoint supports filters and pagination.
|
||||||
The CLI command `kc.[sh|bat] import` now has placeholder replacement enabled. Previously placeholder replacement was only enabled for realm import at startup.
|
The CLI command `kc.[sh|bat] import` now has placeholder replacement enabled. Previously placeholder replacement was only enabled for realm import at startup.
|
||||||
|
|
||||||
If you wish to disable placeholder replacement for the `import` command, add the system property `-Dkeycloak.migration.replace-placeholders=false`
|
If you wish to disable placeholder replacement for the `import` command, add the system property `-Dkeycloak.migration.replace-placeholders=false`
|
||||||
|
|
||||||
|
= Keystore and trust store default format change
|
||||||
|
|
||||||
|
{project_name} now determines the format of the keystore and trust store based on the file extension. If the file extension is `.p12`, `.pkcs12` or `.pfx`, the format is PKCS12. If the file extension is `.jks`, `.keystore` or `.truststore`, the format is JKS. If the file extension is `.pem`, `.crt` or `.key`, the format is PEM.
|
||||||
|
|
||||||
|
You can still override automatic detection by specifying the `https-key-store-type` and `https-trust-store-type` explicitly. The same applies to the management interface and its `https-management-key-store-type`. Restrictions for the FIPS strict mode stay unchanged.
|
||||||
|
|
||||||
|
NOTE: The `+spi-truststore-file-*+` options and the truststore related options `+https-trust-store-*+` are deprecated, we strongly recommend to use System Truststore. For more details refer to the relevant https://www.keycloak.org/server/keycloak-truststore[guide].
|
||||||
|
|
|
@ -165,7 +165,7 @@
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<properties>
|
<properties>
|
||||||
<quarkus.package.filter-optional-dependencies>true</quarkus.package.filter-optional-dependencies>
|
<quarkus.package.jar.filter-optional-dependencies>true</quarkus.package.jar.filter-optional-dependencies>
|
||||||
</properties>
|
</properties>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
|
|
16
pom.xml
16
pom.xml
|
@ -51,8 +51,8 @@
|
||||||
<jboss.snapshots.repo.id>jboss-snapshots-repository</jboss.snapshots.repo.id>
|
<jboss.snapshots.repo.id>jboss-snapshots-repository</jboss.snapshots.repo.id>
|
||||||
<jboss.snapshots.repo.url>https://s01.oss.sonatype.org/content/repositories/snapshots/</jboss.snapshots.repo.url>
|
<jboss.snapshots.repo.url>https://s01.oss.sonatype.org/content/repositories/snapshots/</jboss.snapshots.repo.url>
|
||||||
|
|
||||||
<quarkus.version>3.8.5</quarkus.version>
|
<quarkus.version>3.13.2</quarkus.version>
|
||||||
<quarkus.build.version>3.8.5</quarkus.build.version>
|
<quarkus.build.version>3.13.2</quarkus.build.version>
|
||||||
|
|
||||||
<project.build-time>${timestamp}</project.build-time>
|
<project.build-time>${timestamp}</project.build-time>
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
<jboss.spec.javax.servlet.jsp.jboss-jsp-api_2.3_spec.version>2.0.0.Final</jboss.spec.javax.servlet.jsp.jboss-jsp-api_2.3_spec.version>
|
<jboss.spec.javax.servlet.jsp.jboss-jsp-api_2.3_spec.version>2.0.0.Final</jboss.spec.javax.servlet.jsp.jboss-jsp-api_2.3_spec.version>
|
||||||
<log4j.version>1.2.17</log4j.version>
|
<log4j.version>1.2.17</log4j.version>
|
||||||
<resteasy-legacy.version>4.7.7.Final</resteasy-legacy.version>
|
<resteasy-legacy.version>4.7.7.Final</resteasy-legacy.version>
|
||||||
<resteasy.version>6.2.7.Final</resteasy.version>
|
<resteasy.version>6.2.9.Final</resteasy.version>
|
||||||
<resteasy.undertow.version>${resteasy.version}</resteasy.undertow.version>
|
<resteasy.undertow.version>${resteasy.version}</resteasy.undertow.version>
|
||||||
<owasp.html.sanitizer.version>20240325.1</owasp.html.sanitizer.version>
|
<owasp.html.sanitizer.version>20240325.1</owasp.html.sanitizer.version>
|
||||||
<slf4j.version>2.0.6</slf4j.version>
|
<slf4j.version>2.0.6</slf4j.version>
|
||||||
|
@ -124,7 +124,7 @@
|
||||||
<undertow.version>${undertow-legacy.version}</undertow.version>
|
<undertow.version>${undertow-legacy.version}</undertow.version>
|
||||||
<undertow-legacy.version>2.2.24.Final</undertow-legacy.version>
|
<undertow-legacy.version>2.2.24.Final</undertow-legacy.version>
|
||||||
<undertow-jakarta.version>2.3.2.Final</undertow-jakarta.version>
|
<undertow-jakarta.version>2.3.2.Final</undertow-jakarta.version>
|
||||||
<wildfly-elytron.version>2.2.3.Final</wildfly-elytron.version>
|
<wildfly-elytron.version>2.5.0.Final</wildfly-elytron.version>
|
||||||
<elytron.undertow-server.version>1.9.0.Final</elytron.undertow-server.version>
|
<elytron.undertow-server.version>1.9.0.Final</elytron.undertow-server.version>
|
||||||
<woodstox.version>6.0.3</woodstox.version>
|
<woodstox.version>6.0.3</woodstox.version>
|
||||||
<wildfly.common.quarkus.aligned.version>1.5.4.Final-format-001</wildfly.common.quarkus.aligned.version>
|
<wildfly.common.quarkus.aligned.version>1.5.4.Final-format-001</wildfly.common.quarkus.aligned.version>
|
||||||
|
@ -148,7 +148,7 @@
|
||||||
<com.apicatalog.titanium-json-ld.version>1.3.3</com.apicatalog.titanium-json-ld.version>
|
<com.apicatalog.titanium-json-ld.version>1.3.3</com.apicatalog.titanium-json-ld.version>
|
||||||
<io.setl.rdf-urdna.version>1.1</io.setl.rdf-urdna.version>
|
<io.setl.rdf-urdna.version>1.1</io.setl.rdf-urdna.version>
|
||||||
|
|
||||||
<liquibase.version>4.25.1</liquibase.version>
|
<liquibase.version>4.27.0</liquibase.version>
|
||||||
<servlet.api.30.version>1.0.2.Final</servlet.api.30.version>
|
<servlet.api.30.version>1.0.2.Final</servlet.api.30.version>
|
||||||
<servlet.api.40.version>2.0.0.Final</servlet.api.40.version>
|
<servlet.api.40.version>2.0.0.Final</servlet.api.40.version>
|
||||||
<twitter4j.version>4.1.2</twitter4j.version>
|
<twitter4j.version>4.1.2</twitter4j.version>
|
||||||
|
@ -159,12 +159,12 @@
|
||||||
<postgresql.version>16</postgresql.version>
|
<postgresql.version>16</postgresql.version>
|
||||||
<aurora-postgresql.version>16.1</aurora-postgresql.version>
|
<aurora-postgresql.version>16.1</aurora-postgresql.version>
|
||||||
<aws-jdbc-wrapper.version>2.3.1</aws-jdbc-wrapper.version>
|
<aws-jdbc-wrapper.version>2.3.1</aws-jdbc-wrapper.version>
|
||||||
<postgresql-jdbc.version>42.7.2</postgresql-jdbc.version>
|
<postgresql-jdbc.version>42.7.3</postgresql-jdbc.version>
|
||||||
<mariadb.version>10.11</mariadb.version>
|
<mariadb.version>10.11</mariadb.version>
|
||||||
<mariadb-jdbc.version>3.3.3</mariadb-jdbc.version>
|
<mariadb-jdbc.version>3.4.0</mariadb-jdbc.version>
|
||||||
<mssql.version>2022-latest</mssql.version>
|
<mssql.version>2022-latest</mssql.version>
|
||||||
<!-- this is the mssql driver version also used in the Quarkus BOM -->
|
<!-- this is the mssql driver version also used in the Quarkus BOM -->
|
||||||
<mssql-jdbc.version>12.4.2.jre11</mssql-jdbc.version>
|
<mssql-jdbc.version>12.6.3.jre11</mssql-jdbc.version>
|
||||||
<oracledb.version>19.3</oracledb.version>
|
<oracledb.version>19.3</oracledb.version>
|
||||||
<!-- this is the oracle driver version also used in the Quarkus BOM -->
|
<!-- this is the oracle driver version also used in the Quarkus BOM -->
|
||||||
<oracle-jdbc.version>23.3.0.23.09</oracle-jdbc.version>
|
<oracle-jdbc.version>23.3.0.23.09</oracle-jdbc.version>
|
||||||
|
|
|
@ -87,7 +87,7 @@ public class HttpOptions {
|
||||||
public static final Option<String> HTTPS_KEY_STORE_TYPE = new OptionBuilder<>("https-key-store-type", String.class)
|
public static final Option<String> HTTPS_KEY_STORE_TYPE = new OptionBuilder<>("https-key-store-type", String.class)
|
||||||
.category(OptionCategory.HTTP)
|
.category(OptionCategory.HTTP)
|
||||||
.description("The type of the key store file. " +
|
.description("The type of the key store file. " +
|
||||||
"If not given, the type is automatically detected based on the file name. " +
|
"If not given, the type is automatically detected based on the file extension. " +
|
||||||
"If '" + SecurityOptions.FIPS_MODE.getKey() + "' is set to '" + FipsMode.STRICT + "' and no value is set, it defaults to 'BCFKS'.")
|
"If '" + SecurityOptions.FIPS_MODE.getKey() + "' is set to '" + FipsMode.STRICT + "' and no value is set, it defaults to 'BCFKS'.")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ public class HttpOptions {
|
||||||
public static final Option<String> HTTPS_TRUST_STORE_TYPE = new OptionBuilder<>("https-trust-store-type", String.class)
|
public static final Option<String> HTTPS_TRUST_STORE_TYPE = new OptionBuilder<>("https-trust-store-type", String.class)
|
||||||
.category(OptionCategory.HTTP)
|
.category(OptionCategory.HTTP)
|
||||||
.description("The type of the trust store file. " +
|
.description("The type of the trust store file. " +
|
||||||
"If not given, the type is automatically detected based on the file name. " +
|
"If not given, the type is automatically detected based on the file extension. " +
|
||||||
"If '" + SecurityOptions.FIPS_MODE.getKey() + "' is set to '" + FipsMode.STRICT + "' and no value is set, it defaults to 'BCFKS'.")
|
"If '" + SecurityOptions.FIPS_MODE.getKey() + "' is set to '" + FipsMode.STRICT + "' and no value is set, it defaults to 'BCFKS'.")
|
||||||
.deprecated("Use the System Truststore instead, see the docs for details.")
|
.deprecated("Use the System Truststore instead, see the docs for details.")
|
||||||
.build();
|
.build();
|
||||||
|
|
|
@ -22,7 +22,6 @@ import io.quarkus.agroal.spi.JdbcDataSourceBuildItem;
|
||||||
import io.quarkus.agroal.spi.JdbcDriverBuildItem;
|
import io.quarkus.agroal.spi.JdbcDriverBuildItem;
|
||||||
import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem;
|
import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem;
|
||||||
import io.quarkus.arc.deployment.BuildTimeConditionBuildItem;
|
import io.quarkus.arc.deployment.BuildTimeConditionBuildItem;
|
||||||
import io.quarkus.arc.processor.AnnotationsTransformer;
|
|
||||||
import io.quarkus.bootstrap.logging.InitialConfigurator;
|
import io.quarkus.bootstrap.logging.InitialConfigurator;
|
||||||
import io.quarkus.datasource.deployment.spi.DevServicesDatasourceResultBuildItem;
|
import io.quarkus.datasource.deployment.spi.DevServicesDatasourceResultBuildItem;
|
||||||
import io.quarkus.deployment.IsDevelopment;
|
import io.quarkus.deployment.IsDevelopment;
|
||||||
|
@ -50,10 +49,12 @@ import io.quarkus.vertx.http.deployment.RouteBuildItem;
|
||||||
import io.smallrye.config.ConfigValue;
|
import io.smallrye.config.ConfigValue;
|
||||||
import org.eclipse.microprofile.health.Readiness;
|
import org.eclipse.microprofile.health.Readiness;
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
|
||||||
import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
|
import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
|
||||||
import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
|
import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
|
||||||
import org.jboss.jandex.AnnotationInstance;
|
import org.jboss.jandex.AnnotationInstance;
|
||||||
import org.jboss.jandex.AnnotationTarget;
|
import org.jboss.jandex.AnnotationTarget;
|
||||||
|
import org.jboss.jandex.AnnotationTransformation;
|
||||||
import org.jboss.jandex.ClassInfo;
|
import org.jboss.jandex.ClassInfo;
|
||||||
import org.jboss.jandex.DotName;
|
import org.jboss.jandex.DotName;
|
||||||
import org.jboss.jandex.IndexView;
|
import org.jboss.jandex.IndexView;
|
||||||
|
@ -318,7 +319,7 @@ class KeycloakProcessor {
|
||||||
List<String> userManagedEntities = new ArrayList<>();
|
List<String> userManagedEntities = new ArrayList<>();
|
||||||
|
|
||||||
for (PersistenceXmlDescriptorBuildItem item : descriptors) {
|
for (PersistenceXmlDescriptorBuildItem item : descriptors) {
|
||||||
ParsedPersistenceXmlDescriptor descriptor = item.getDescriptor();
|
ParsedPersistenceXmlDescriptor descriptor = (ParsedPersistenceXmlDescriptor) item.getDescriptor();
|
||||||
|
|
||||||
if ("keycloak-default".equals(descriptor.getName())) {
|
if ("keycloak-default".equals(descriptor.getName())) {
|
||||||
defaultUnitDescriptor = descriptor;
|
defaultUnitDescriptor = descriptor;
|
||||||
|
@ -469,7 +470,7 @@ class KeycloakProcessor {
|
||||||
Map<String, ProviderFactory> preConfiguredProviders, Spi spi) {
|
Map<String, ProviderFactory> preConfiguredProviders, Spi spi) {
|
||||||
descriptors.stream()
|
descriptors.stream()
|
||||||
.map(PersistenceXmlDescriptorBuildItem::getDescriptor)
|
.map(PersistenceXmlDescriptorBuildItem::getDescriptor)
|
||||||
.map(ParsedPersistenceXmlDescriptor::getName)
|
.map(PersistenceUnitDescriptor::getName)
|
||||||
.filter(Predicate.not("keycloak-default"::equals)).forEach((String unitName) -> {
|
.filter(Predicate.not("keycloak-default"::equals)).forEach((String unitName) -> {
|
||||||
NamedJpaConnectionProviderFactory factory = new NamedJpaConnectionProviderFactory();
|
NamedJpaConnectionProviderFactory factory = new NamedJpaConnectionProviderFactory();
|
||||||
|
|
||||||
|
@ -625,9 +626,9 @@ class KeycloakProcessor {
|
||||||
// bean without the @Readiness annotation so it won't be used as a health check on it's own.
|
// bean without the @Readiness annotation so it won't be used as a health check on it's own.
|
||||||
@BuildStep
|
@BuildStep
|
||||||
AnnotationsTransformerBuildItem disableDefaultDataSourceHealthCheck() {
|
AnnotationsTransformerBuildItem disableDefaultDataSourceHealthCheck() {
|
||||||
return new AnnotationsTransformerBuildItem(AnnotationsTransformer.appliedToClass()
|
return new AnnotationsTransformerBuildItem(AnnotationTransformation.forClasses()
|
||||||
.whenClass(c -> c.name().equals(DotName.createSimple(DataSourceHealthCheck.class)))
|
.whenClass(c -> c.name().equals(DotName.createSimple(DataSourceHealthCheck.class)))
|
||||||
.thenTransform(t -> t.remove(
|
.transform(t -> t.remove(
|
||||||
a -> a.name().equals(DotName.createSimple(Readiness.class)))));
|
a -> a.name().equals(DotName.createSimple(Readiness.class)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,4 +23,8 @@ public class PropertyException extends RuntimeException {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PropertyException(String message, Throwable throwable) {
|
||||||
|
super(message, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import static org.keycloak.quarkus.runtime.Environment.isDevProfile;
|
||||||
import static org.keycloak.quarkus.runtime.cli.Picocli.println;
|
import static org.keycloak.quarkus.runtime.cli.Picocli.println;
|
||||||
import static org.keycloak.quarkus.runtime.configuration.ConfigArgsConfigSource.getAllCliArgs;
|
import static org.keycloak.quarkus.runtime.configuration.ConfigArgsConfigSource.getAllCliArgs;
|
||||||
|
|
||||||
|
import io.quarkus.runtime.LaunchMode;
|
||||||
import org.keycloak.config.OptionCategory;
|
import org.keycloak.config.OptionCategory;
|
||||||
import org.keycloak.quarkus.runtime.Environment;
|
import org.keycloak.quarkus.runtime.Environment;
|
||||||
import org.keycloak.quarkus.runtime.Messages;
|
import org.keycloak.quarkus.runtime.Messages;
|
||||||
|
@ -31,7 +32,6 @@ import org.keycloak.quarkus.runtime.configuration.Configuration;
|
||||||
import io.quarkus.bootstrap.runner.QuarkusEntryPoint;
|
import io.quarkus.bootstrap.runner.QuarkusEntryPoint;
|
||||||
import io.quarkus.bootstrap.runner.RunnerClassLoader;
|
import io.quarkus.bootstrap.runner.RunnerClassLoader;
|
||||||
|
|
||||||
import io.quarkus.runtime.configuration.ProfileManager;
|
|
||||||
import io.smallrye.config.ConfigValue;
|
import io.smallrye.config.ConfigValue;
|
||||||
import picocli.CommandLine;
|
import picocli.CommandLine;
|
||||||
import picocli.CommandLine.Command;
|
import picocli.CommandLine.Command;
|
||||||
|
@ -131,7 +131,7 @@ public final class Build extends AbstractCommand implements Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cleanTempResources() {
|
private void cleanTempResources() {
|
||||||
if (!ProfileManager.getLaunchMode().isDevOrTest()) {
|
if (!LaunchMode.current().isDevOrTest()) {
|
||||||
// only needed for dev/testing purposes
|
// only needed for dev/testing purposes
|
||||||
getHomePath().resolve("quarkus-artifact.properties").toFile().delete();
|
getHomePath().resolve("quarkus-artifact.properties").toFile().delete();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import io.smallrye.config.ConfigValue;
|
||||||
import io.smallrye.config.PropertiesConfigSource;
|
import io.smallrye.config.PropertiesConfigSource;
|
||||||
|
|
||||||
import org.keycloak.quarkus.runtime.cli.command.Main;
|
import org.keycloak.quarkus.runtime.cli.command.Main;
|
||||||
|
@ -91,15 +92,14 @@ public class ConfigArgsConfigSource extends PropertiesConfigSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getValue(String propertyName) {
|
public ConfigValue getConfigValue(String propertyName) {
|
||||||
Map<String, String> properties = getProperties();
|
ConfigValue value = super.getConfigValue(propertyName);
|
||||||
String value = properties.get(propertyName);
|
|
||||||
|
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return properties.get(propertyName.replace(OPTION_PART_SEPARATOR_CHAR, '.'));
|
return super.getConfigValue(propertyName.replace(OPTION_PART_SEPARATOR_CHAR, '.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String, String> parseArguments() {
|
private static Map<String, String> parseArguments() {
|
||||||
|
|
|
@ -63,7 +63,21 @@ public class KeycloakPropertiesConfigSource extends AbstractLocationConfigSource
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ConfigSource loadConfigSource(URL url, int ordinal) throws IOException {
|
protected ConfigSource loadConfigSource(URL url, int ordinal) throws IOException {
|
||||||
return new PropertiesConfigSource(transform(ConfigSourceUtil.urlToMap(url)), url.toString(), ordinal);
|
// a workaround for https://github.com/smallrye/smallrye-config/issues/1207
|
||||||
|
// replace by the following line when fixed:
|
||||||
|
// return new PropertiesConfigSource(transform(ConfigSourceUtil.urlToMap(url)), url.toString(), ordinal);
|
||||||
|
var cs = new PropertiesConfigSource(transform(ConfigSourceUtil.urlToMap(url)), url.toString(), ordinal) {
|
||||||
|
private String name;
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
cs.setName(url.toString());
|
||||||
|
return cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class InClassPath extends KeycloakPropertiesConfigSource implements ConfigSourceProvider {
|
public static class InClassPath extends KeycloakPropertiesConfigSource implements ConfigSourceProvider {
|
||||||
|
|
|
@ -32,6 +32,7 @@ import java.util.function.Supplier;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
import io.smallrye.config.ConfigValue;
|
||||||
import io.smallrye.config.PropertiesConfigSource;
|
import io.smallrye.config.PropertiesConfigSource;
|
||||||
import org.keycloak.quarkus.runtime.Environment;
|
import org.keycloak.quarkus.runtime.Environment;
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ public final class PersistedConfigSource extends PropertiesConfigSource {
|
||||||
private static final ThreadLocal<Boolean> ENABLED = ThreadLocal.withInitial(() -> true);
|
private static final ThreadLocal<Boolean> ENABLED = ThreadLocal.withInitial(() -> true);
|
||||||
|
|
||||||
private PersistedConfigSource() {
|
private PersistedConfigSource() {
|
||||||
super(readProperties(), "", 200);
|
super(readProperties(), NAME, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PersistedConfigSource getInstance() {
|
public static PersistedConfigSource getInstance() {
|
||||||
|
@ -67,15 +68,15 @@ public final class PersistedConfigSource extends PropertiesConfigSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getValue(String propertyName) {
|
public ConfigValue getConfigValue(String propertyName) {
|
||||||
if (isEnabled()) {
|
if (isEnabled()) {
|
||||||
String value = super.getValue(propertyName);
|
ConfigValue value = super.getConfigValue(propertyName);
|
||||||
|
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.getValue(propertyName.replace(Configuration.OPTION_PART_SEPARATOR_CHAR, '.'));
|
return super.getConfigValue(propertyName.replace(Configuration.OPTION_PART_SEPARATOR_CHAR, '.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -57,7 +57,10 @@ public final class QuarkusPropertiesConfigSource extends AbstractLocationConfigS
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NAME.equals(value.getConfigSourceName());
|
// workaround for https://github.com/smallrye/smallrye-config/issues/1207
|
||||||
|
// replace by the following line when fixed:
|
||||||
|
// return NAME.equals(value.getConfigSourceName());
|
||||||
|
return value.getConfigSourceName() != null && value.getConfigSourceName().endsWith(FILE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Path getConfigurationFile() {
|
public static Path getConfigurationFile() {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package org.keycloak.quarkus.runtime.configuration.mappers;
|
package org.keycloak.quarkus.runtime.configuration.mappers;
|
||||||
|
|
||||||
|
import io.quarkus.vertx.http.runtime.CertificateConfig;
|
||||||
|
import io.quarkus.vertx.http.runtime.options.TlsUtils;
|
||||||
import io.smallrye.config.ConfigSourceInterceptorContext;
|
import io.smallrye.config.ConfigSourceInterceptorContext;
|
||||||
|
|
||||||
import org.keycloak.common.crypto.FipsMode;
|
import org.keycloak.common.crypto.FipsMode;
|
||||||
|
@ -11,6 +13,7 @@ import org.keycloak.quarkus.runtime.cli.PropertyException;
|
||||||
import org.keycloak.quarkus.runtime.configuration.Configuration;
|
import org.keycloak.quarkus.runtime.configuration.Configuration;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
@ -127,6 +130,52 @@ public final class HttpPropertyMappers {
|
||||||
|
|
||||||
public static void validateConfig() {
|
public static void validateConfig() {
|
||||||
boolean enabled = isHttpEnabled(Configuration.getOptionalKcValue(HttpOptions.HTTP_ENABLED.getKey()));
|
boolean enabled = isHttpEnabled(Configuration.getOptionalKcValue(HttpOptions.HTTP_ENABLED.getKey()));
|
||||||
|
boolean trustStoreFile = Configuration.getOptionalKcValue(HttpOptions.HTTPS_TRUST_STORE_FILE.getKey()).isPresent();
|
||||||
|
boolean keyStoreFile = Configuration.getOptionalKcValue(HttpOptions.HTTPS_KEY_STORE_FILE.getKey()).isPresent();
|
||||||
|
|
||||||
|
if (trustStoreFile) {
|
||||||
|
CertificateConfig config = new CertificateConfig();
|
||||||
|
|
||||||
|
config.trustStoreFile = Configuration.getOptionalKcValue(HttpOptions.HTTPS_TRUST_STORE_FILE.getKey()).map(Paths::get);
|
||||||
|
config.trustStorePassword = Configuration.getOptionalKcValue(HttpOptions.HTTPS_TRUST_STORE_PASSWORD.getKey());
|
||||||
|
config.trustStoreFileType = Configuration.getOptionalKcValue(HttpOptions.HTTPS_TRUST_STORE_TYPE.getKey());
|
||||||
|
config.trustStoreProvider = Configuration.getOptionalValue("quarkus.http.ssl.certificate.trust-store-provider");
|
||||||
|
config.trustStoreCertAlias = Configuration.getOptionalValue("quarkus.http.ssl.certificate.trust-store-cert-alias");
|
||||||
|
config.trustStoreFiles = Optional.empty();
|
||||||
|
|
||||||
|
try {
|
||||||
|
TlsUtils.computeTrustOptions(config, config.trustStorePassword);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new PropertyException("Failed to load 'https-trust-store' material.", e);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new PropertyException("Unable to determine 'https-trust-store-type' automatically. " +
|
||||||
|
"Adjust the file extension or specify the property.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyStoreFile) {
|
||||||
|
CertificateConfig config = new CertificateConfig();
|
||||||
|
|
||||||
|
config.keyStoreFile = Configuration.getOptionalKcValue(HttpOptions.HTTPS_KEY_STORE_FILE.getKey()).map(Paths::get);
|
||||||
|
config.keyStorePassword = Configuration.getOptionalKcValue(HttpOptions.HTTPS_KEY_STORE_PASSWORD.getKey());
|
||||||
|
config.keyStoreFileType = Configuration.getOptionalKcValue(HttpOptions.HTTPS_KEY_STORE_TYPE.getKey());
|
||||||
|
config.keyStoreProvider = Configuration.getOptionalValue("quarkus.http.ssl.certificate.key-store-provider");
|
||||||
|
config.keyStoreAlias = Configuration.getOptionalValue("quarkus.http.ssl.certificate.key-store-alias");
|
||||||
|
config.keyStoreAliasPassword = Configuration.getOptionalValue("quarkus.http.ssl.certificate.key-store-alias-password");
|
||||||
|
config.keyStoreAliasPasswordKey = Configuration.getOptionalValue("quarkus.http.ssl.certificate.key-store-alias-password-key");
|
||||||
|
config.keyStoreKeyAlias = Configuration.getOptionalValue("quarkus.http.ssl.certificate.key-store-key-alias");
|
||||||
|
config.keyFiles = Optional.empty();
|
||||||
|
config.files = Optional.empty();
|
||||||
|
|
||||||
|
try {
|
||||||
|
TlsUtils.computeKeyStoreOptions(config, config.keyStorePassword, config.keyStoreAliasPassword);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new PropertyException("Failed to load 'https-key-store' material.", e);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new PropertyException("Unable to determine 'https-key-store-type' automatically. " +
|
||||||
|
"Adjust the file extension or specify the property.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
Optional<String> value = Configuration.getOptionalKcValue(HttpOptions.HTTPS_CERTIFICATE_FILE.getKey());
|
Optional<String> value = Configuration.getOptionalKcValue(HttpOptions.HTTPS_CERTIFICATE_FILE.getKey());
|
||||||
|
|
|
@ -18,7 +18,7 @@ quarkus.transaction-manager.default-transaction-timeout=300
|
||||||
quarkus.arc.ignored-split-packages=org.keycloak.*
|
quarkus.arc.ignored-split-packages=org.keycloak.*
|
||||||
|
|
||||||
# No need to generate dependencies list
|
# No need to generate dependencies list
|
||||||
quarkus.package.include-dependency-list=false
|
quarkus.package.jar.include-dependency-list=false
|
||||||
|
|
||||||
# we do not want running dev services in distribution
|
# we do not want running dev services in distribution
|
||||||
quarkus.devservices.enabled=false
|
quarkus.devservices.enabled=false
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Inherit all configuration from the default runtime settings and sets those specific to the distribution
|
# Inherit all configuration from the default runtime settings and sets those specific to the distribution
|
||||||
|
|
||||||
quarkus.package.output-name=keycloak
|
quarkus.package.output-name=keycloak
|
||||||
quarkus.package.type=mutable-jar
|
quarkus.package.jar.type=mutable-jar
|
||||||
quarkus.package.output-directory=lib
|
quarkus.package.output-directory=lib
|
||||||
quarkus.package.user-providers-directory=../providers
|
quarkus.package.jar.user-providers-directory=../providers
|
||||||
quarkus.package.main-class=keycloak
|
quarkus.package.main-class=keycloak
|
|
@ -117,6 +117,7 @@
|
||||||
<argLine>-Djdk.net.hosts.file=${project.build.testOutputDirectory}/hosts_file -XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError --add-opens=java.base/java.security=ALL-UNNAMED -Djava.util.concurrent.ForkJoinPool.common.threadFactory=io.quarkus.bootstrap.forkjoin.QuarkusForkJoinWorkerThreadFactory</argLine>
|
<argLine>-Djdk.net.hosts.file=${project.build.testOutputDirectory}/hosts_file -XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError --add-opens=java.base/java.security=ALL-UNNAMED -Djava.util.concurrent.ForkJoinPool.common.threadFactory=io.quarkus.bootstrap.forkjoin.QuarkusForkJoinWorkerThreadFactory</argLine>
|
||||||
<systemPropertyVariables>
|
<systemPropertyVariables>
|
||||||
<kc.quarkus.tests.dist>${kc.quarkus.tests.dist}</kc.quarkus.tests.dist>
|
<kc.quarkus.tests.dist>${kc.quarkus.tests.dist}</kc.quarkus.tests.dist>
|
||||||
|
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
|
@ -147,9 +147,19 @@ public class FipsDistTest {
|
||||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||||
Path truststorePath = rawDist.getDistPath().resolve("conf").resolve("server.keystore").toAbsolutePath();
|
Path truststorePath = rawDist.getDistPath().resolve("conf").resolve("server.keystore").toAbsolutePath();
|
||||||
|
|
||||||
// https-trust-store-type should be automatically set to pkcs12 in fips-mode=non-strict
|
|
||||||
CLIResult cliResult = dist.run("--verbose", "start", "--fips-mode=non-strict", "--https-key-store-password=passwordpassword",
|
CLIResult cliResult = dist.run("--verbose", "start", "--fips-mode=non-strict", "--https-key-store-password=passwordpassword",
|
||||||
"--https-trust-store-file=" + truststorePath, "--https-trust-store-password=passwordpassword");
|
"--https-trust-store-file=" + truststorePath, "--https-trust-store-password=passwordpassword");
|
||||||
|
cliResult.assertError("Unable to determine 'https-trust-store-type' automatically. Adjust the file extension or specify the property.");
|
||||||
|
|
||||||
|
dist.stop();
|
||||||
|
|
||||||
|
dist.copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.p12"));
|
||||||
|
|
||||||
|
rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||||
|
truststorePath = rawDist.getDistPath().resolve("conf").resolve("server.p12").toAbsolutePath();
|
||||||
|
|
||||||
|
cliResult = dist.run("--verbose", "start", "--fips-mode=non-strict", "--https-key-store-password=passwordpassword",
|
||||||
|
"--https-trust-store-file=" + truststorePath, "--https-trust-store-password=passwordpassword");
|
||||||
cliResult.assertStarted();
|
cliResult.assertStarted();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,8 +165,8 @@ HTTP(S):
|
||||||
The password of the key store file. Default: password.
|
The password of the key store file. Default: password.
|
||||||
--https-key-store-type <type>
|
--https-key-store-type <type>
|
||||||
The type of the key store file. If not given, the type is automatically
|
The type of the key store file. If not given, the type is automatically
|
||||||
detected based on the file name. If 'fips-mode' is set to 'strict' and no
|
detected based on the file extension. If 'fips-mode' is set to 'strict' and
|
||||||
value is set, it defaults to 'BCFKS'.
|
no value is set, it defaults to 'BCFKS'.
|
||||||
--https-port <port> The used HTTPS port. Default: 8443.
|
--https-port <port> The used HTTPS port. Default: 8443.
|
||||||
--https-protocols <protocols>
|
--https-protocols <protocols>
|
||||||
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
|
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
|
||||||
|
@ -179,7 +179,7 @@ HTTP(S):
|
||||||
instead, see the docs for details.
|
instead, see the docs for details.
|
||||||
--https-trust-store-type <type>
|
--https-trust-store-type <type>
|
||||||
DEPRECATED. The type of the trust store file. If not given, the type is
|
DEPRECATED. The type of the trust store file. If not given, the type is
|
||||||
automatically detected based on the file name. If 'fips-mode' is set to
|
automatically detected based on the file extension. If 'fips-mode' is set to
|
||||||
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
|
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
|
||||||
Truststore instead, see the docs for details.
|
Truststore instead, see the docs for details.
|
||||||
|
|
||||||
|
|
|
@ -237,8 +237,8 @@ HTTP(S):
|
||||||
The password of the key store file. Default: password.
|
The password of the key store file. Default: password.
|
||||||
--https-key-store-type <type>
|
--https-key-store-type <type>
|
||||||
The type of the key store file. If not given, the type is automatically
|
The type of the key store file. If not given, the type is automatically
|
||||||
detected based on the file name. If 'fips-mode' is set to 'strict' and no
|
detected based on the file extension. If 'fips-mode' is set to 'strict' and
|
||||||
value is set, it defaults to 'BCFKS'.
|
no value is set, it defaults to 'BCFKS'.
|
||||||
--https-port <port> The used HTTPS port. Default: 8443.
|
--https-port <port> The used HTTPS port. Default: 8443.
|
||||||
--https-protocols <protocols>
|
--https-protocols <protocols>
|
||||||
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
|
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
|
||||||
|
@ -251,7 +251,7 @@ HTTP(S):
|
||||||
instead, see the docs for details.
|
instead, see the docs for details.
|
||||||
--https-trust-store-type <type>
|
--https-trust-store-type <type>
|
||||||
DEPRECATED. The type of the trust store file. If not given, the type is
|
DEPRECATED. The type of the trust store file. If not given, the type is
|
||||||
automatically detected based on the file name. If 'fips-mode' is set to
|
automatically detected based on the file extension. If 'fips-mode' is set to
|
||||||
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
|
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
|
||||||
Truststore instead, see the docs for details.
|
Truststore instead, see the docs for details.
|
||||||
|
|
||||||
|
|
|
@ -166,8 +166,8 @@ HTTP(S):
|
||||||
The password of the key store file. Default: password.
|
The password of the key store file. Default: password.
|
||||||
--https-key-store-type <type>
|
--https-key-store-type <type>
|
||||||
The type of the key store file. If not given, the type is automatically
|
The type of the key store file. If not given, the type is automatically
|
||||||
detected based on the file name. If 'fips-mode' is set to 'strict' and no
|
detected based on the file extension. If 'fips-mode' is set to 'strict' and
|
||||||
value is set, it defaults to 'BCFKS'.
|
no value is set, it defaults to 'BCFKS'.
|
||||||
--https-port <port> The used HTTPS port. Default: 8443.
|
--https-port <port> The used HTTPS port. Default: 8443.
|
||||||
--https-protocols <protocols>
|
--https-protocols <protocols>
|
||||||
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
|
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
|
||||||
|
@ -180,7 +180,7 @@ HTTP(S):
|
||||||
instead, see the docs for details.
|
instead, see the docs for details.
|
||||||
--https-trust-store-type <type>
|
--https-trust-store-type <type>
|
||||||
DEPRECATED. The type of the trust store file. If not given, the type is
|
DEPRECATED. The type of the trust store file. If not given, the type is
|
||||||
automatically detected based on the file name. If 'fips-mode' is set to
|
automatically detected based on the file extension. If 'fips-mode' is set to
|
||||||
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
|
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
|
||||||
Truststore instead, see the docs for details.
|
Truststore instead, see the docs for details.
|
||||||
|
|
||||||
|
|
|
@ -238,8 +238,8 @@ HTTP(S):
|
||||||
The password of the key store file. Default: password.
|
The password of the key store file. Default: password.
|
||||||
--https-key-store-type <type>
|
--https-key-store-type <type>
|
||||||
The type of the key store file. If not given, the type is automatically
|
The type of the key store file. If not given, the type is automatically
|
||||||
detected based on the file name. If 'fips-mode' is set to 'strict' and no
|
detected based on the file extension. If 'fips-mode' is set to 'strict' and
|
||||||
value is set, it defaults to 'BCFKS'.
|
no value is set, it defaults to 'BCFKS'.
|
||||||
--https-port <port> The used HTTPS port. Default: 8443.
|
--https-port <port> The used HTTPS port. Default: 8443.
|
||||||
--https-protocols <protocols>
|
--https-protocols <protocols>
|
||||||
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
|
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
|
||||||
|
@ -252,7 +252,7 @@ HTTP(S):
|
||||||
instead, see the docs for details.
|
instead, see the docs for details.
|
||||||
--https-trust-store-type <type>
|
--https-trust-store-type <type>
|
||||||
DEPRECATED. The type of the trust store file. If not given, the type is
|
DEPRECATED. The type of the trust store file. If not given, the type is
|
||||||
automatically detected based on the file name. If 'fips-mode' is set to
|
automatically detected based on the file extension. If 'fips-mode' is set to
|
||||||
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
|
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
|
||||||
Truststore instead, see the docs for details.
|
Truststore instead, see the docs for details.
|
||||||
|
|
||||||
|
|
|
@ -145,8 +145,8 @@ HTTP(S):
|
||||||
The password of the key store file. Default: password.
|
The password of the key store file. Default: password.
|
||||||
--https-key-store-type <type>
|
--https-key-store-type <type>
|
||||||
The type of the key store file. If not given, the type is automatically
|
The type of the key store file. If not given, the type is automatically
|
||||||
detected based on the file name. If 'fips-mode' is set to 'strict' and no
|
detected based on the file extension. If 'fips-mode' is set to 'strict' and
|
||||||
value is set, it defaults to 'BCFKS'.
|
no value is set, it defaults to 'BCFKS'.
|
||||||
--https-port <port> The used HTTPS port. Default: 8443.
|
--https-port <port> The used HTTPS port. Default: 8443.
|
||||||
--https-protocols <protocols>
|
--https-protocols <protocols>
|
||||||
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
|
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
|
||||||
|
@ -159,7 +159,7 @@ HTTP(S):
|
||||||
instead, see the docs for details.
|
instead, see the docs for details.
|
||||||
--https-trust-store-type <type>
|
--https-trust-store-type <type>
|
||||||
DEPRECATED. The type of the trust store file. If not given, the type is
|
DEPRECATED. The type of the trust store file. If not given, the type is
|
||||||
automatically detected based on the file name. If 'fips-mode' is set to
|
automatically detected based on the file extension. If 'fips-mode' is set to
|
||||||
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
|
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
|
||||||
Truststore instead, see the docs for details.
|
Truststore instead, see the docs for details.
|
||||||
|
|
||||||
|
|
|
@ -217,8 +217,8 @@ HTTP(S):
|
||||||
The password of the key store file. Default: password.
|
The password of the key store file. Default: password.
|
||||||
--https-key-store-type <type>
|
--https-key-store-type <type>
|
||||||
The type of the key store file. If not given, the type is automatically
|
The type of the key store file. If not given, the type is automatically
|
||||||
detected based on the file name. If 'fips-mode' is set to 'strict' and no
|
detected based on the file extension. If 'fips-mode' is set to 'strict' and
|
||||||
value is set, it defaults to 'BCFKS'.
|
no value is set, it defaults to 'BCFKS'.
|
||||||
--https-port <port> The used HTTPS port. Default: 8443.
|
--https-port <port> The used HTTPS port. Default: 8443.
|
||||||
--https-protocols <protocols>
|
--https-protocols <protocols>
|
||||||
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
|
The list of protocols to explicitly enable. Default: TLSv1.3,TLSv1.2.
|
||||||
|
@ -231,7 +231,7 @@ HTTP(S):
|
||||||
instead, see the docs for details.
|
instead, see the docs for details.
|
||||||
--https-trust-store-type <type>
|
--https-trust-store-type <type>
|
||||||
DEPRECATED. The type of the trust store file. If not given, the type is
|
DEPRECATED. The type of the trust store file. If not given, the type is
|
||||||
automatically detected based on the file name. If 'fips-mode' is set to
|
automatically detected based on the file extension. If 'fips-mode' is set to
|
||||||
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
|
'strict' and no value is set, it defaults to 'BCFKS'. Use the System
|
||||||
Truststore instead, see the docs for details.
|
Truststore instead, see the docs for details.
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,10 @@ public class DefaultEmailSenderProvider implements EmailSenderProvider {
|
||||||
props.put("mail.smtp.ssl.socketFactory", factory);
|
props.put("mail.smtp.ssl.socketFactory", factory);
|
||||||
if (configurator.getProvider().getPolicy() == HostnameVerificationPolicy.ANY) {
|
if (configurator.getProvider().getPolicy() == HostnameVerificationPolicy.ANY) {
|
||||||
props.setProperty("mail.smtp.ssl.trust", "*");
|
props.setProperty("mail.smtp.ssl.trust", "*");
|
||||||
props.put("mail.smtp.ssl.checkserveridentity", Boolean.FALSE.toString());
|
props.put("mail.smtp.ssl.checkserveridentity", Boolean.FALSE.toString()); // this should be the default but seems to be impl specific, so set it explicitly just to be sure
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
props.put("mail.smtp.ssl.checkserveridentity", Boolean.TRUE.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue