Make https-trust-store-type set to bcfks by default in strict-mode
Closes #17119
This commit is contained in:
parent
e76418e3de
commit
4f068fcdcc
20 changed files with 48 additions and 38 deletions
|
|
@ -80,7 +80,6 @@ public class CryptoIntegration {
|
|||
.append(" Default keystore type: " + KeyStore.getDefaultType() + "\n")
|
||||
.append(" KeyManagerFactory.getDefaultAlgorithm(): " + KeyManagerFactory.getDefaultAlgorithm() + "\n")
|
||||
.append(" TrustManagerFactory.getDefaultAlgorithm(): " + TrustManagerFactory.getDefaultAlgorithm() + "\n")
|
||||
.append(" Default keystore type: " + KeyStore.getDefaultType() + "\n")
|
||||
.append(" keystore.type.compat: " + Security.getProperty("keystore.type.compat") + "\n");
|
||||
Stream.of("javax.net.ssl.trustStoreType", "javax.net.ssl.trustStore", "javax.net.ssl.trustStoreProvider",
|
||||
"javax.net.ssl.keyStoreType", "javax.net.ssl.keyStore", "javax.net.ssl.keyStoreProvider")
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ public class KeycloakFipsSecurityProvider extends Provider {
|
|||
super("KC(" +
|
||||
bcFipsProvider.toString() +
|
||||
(isInApprovedOnlyMode() ? " Approved Mode" : "") +
|
||||
(isSystemFipsEnabled() ? " FIPS-enabled JVM" : "") +
|
||||
", FIPS-JVM: " + isSystemFipsEnabled() +
|
||||
")", 1, "Keycloak pseudo provider");
|
||||
this.bcFipsProvider = bcFipsProvider;
|
||||
}
|
||||
|
|
@ -39,22 +39,22 @@ public class KeycloakFipsSecurityProvider extends Provider {
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean isSystemFipsEnabled() {
|
||||
public static String isSystemFipsEnabled() {
|
||||
Method isSystemFipsEnabled = null;
|
||||
|
||||
try {
|
||||
Class<?> securityConfigurator = KeycloakFipsSecurityProvider.class.getClassLoader().loadClass("java.security.SystemConfigurator");
|
||||
isSystemFipsEnabled = securityConfigurator.getDeclaredMethod("isSystemFipsEnabled");
|
||||
isSystemFipsEnabled.setAccessible(true);
|
||||
return (boolean) isSystemFipsEnabled.invoke(null);
|
||||
boolean isEnabled = (boolean) isSystemFipsEnabled.invoke(null);
|
||||
return isEnabled ? "enabled" : "disabled";
|
||||
} catch (Throwable ignore) {
|
||||
logger.debug("Could not detect if FIPS is enabled from the host");
|
||||
logger.debug("Could not detect if FIPS is enabled from the host", ignore);
|
||||
return "unknown";
|
||||
} finally {
|
||||
if (isSystemFipsEnabled != null) {
|
||||
isSystemFipsEnabled.setAccessible(false);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,10 +97,11 @@ public class HttpOptions {
|
|||
.description("The password of the trust store file.")
|
||||
.build();
|
||||
|
||||
public static final Option HTTPS_TRUST_STORE_TYPE = new OptionBuilder<>("https-trust-store-type", File.class)
|
||||
public static final Option<String> HTTPS_TRUST_STORE_TYPE = new OptionBuilder<>("https-trust-store-type", String.class)
|
||||
.category(OptionCategory.HTTP)
|
||||
.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 name. " +
|
||||
"If '" + SecurityOptions.FIPS_MODE.getKey() + "' is set to '" + FipsMode.strict.name() + "' and no value is set, it defaults to 'BCFKS'.")
|
||||
.build();
|
||||
|
||||
public static final Option<Boolean> HTTP_SERVER_ENABLED = new OptionBuilder<>("http-server-enabled", Boolean.class)
|
||||
|
|
|
|||
|
|
@ -98,6 +98,8 @@ final class HttpPropertyMappers {
|
|||
.build(),
|
||||
fromOption(HttpOptions.HTTPS_TRUST_STORE_TYPE)
|
||||
.to("quarkus.http.ssl.certificate.trust-store-file-type")
|
||||
.mapFrom(SecurityOptions.FIPS_MODE.getKey())
|
||||
.transformer(HttpPropertyMappers::resolveKeyStoreType)
|
||||
.paramLabel("type")
|
||||
.build()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.keycloak.it.cli.dist;
|
|||
|
||||
import java.nio.file.Path;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.crypto.fips.KeycloakFipsSecurityProvider;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
|
|
@ -38,7 +39,7 @@ public class FipsDistTest {
|
|||
CLIResult cliResult = dist.run("start", "--fips-mode=enabled");
|
||||
cliResult.assertStarted();
|
||||
cliResult.assertMessage("Java security providers: [ \n"
|
||||
+ " KC(BCFIPS version 1.000203) version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider");
|
||||
+ " KC(BCFIPS version 1.000203, FIPS-JVM: " + KeycloakFipsSecurityProvider.isSystemFipsEnabled() + ") version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +54,7 @@ public class FipsDistTest {
|
|||
cliResult.assertMessage(
|
||||
"org.bouncycastle.crypto.fips.FipsUnapprovedOperationError: password must be at least 112 bits");
|
||||
cliResult.assertMessage("Java security providers: [ \n"
|
||||
+ " KC(BCFIPS version 1.000203 Approved Mode) version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider");
|
||||
+ " KC(BCFIPS version 1.000203 Approved Mode, FIPS-JVM: " + KeycloakFipsSecurityProvider.isSystemFipsEnabled() + ") version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider");
|
||||
|
||||
dist.setEnvVar("KEYCLOAK_ADMIN_PASSWORD", "adminadminadmin");
|
||||
cliResult = dist.run("start", "--fips-mode=strict");
|
||||
|
|
@ -87,6 +88,21 @@ public class FipsDistTest {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHttpsBcfksTrustStoreInStrictMode(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
dist.copyOrReplaceFileFromClasspath("/server.keystore.bcfks", Path.of("conf", "server.keystore"));
|
||||
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
Path truststorePath = rawDist.getDistPath().resolve("conf").resolve("server.keystore").toAbsolutePath();
|
||||
|
||||
// https-trust-store-type should be automatically set to bcfks in fips-mode=strict
|
||||
CLIResult cliResult = dist.run("--verbose", "start", "--fips-mode=strict", "--https-key-store-password=passwordpassword",
|
||||
"--https-trust-store-file=" + truststorePath, "--https-trust-store-password=passwordpassword");
|
||||
cliResult.assertStarted();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUnsupportedHttpsPkcs12KeyStoreInStrictMode(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
|
|
@ -105,6 +121,21 @@ public class FipsDistTest {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHttpsPkcs12TrustStoreInNonApprovedMode(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
dist.copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.keystore"));
|
||||
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
Path truststorePath = rawDist.getDistPath().resolve("conf").resolve("server.keystore").toAbsolutePath();
|
||||
|
||||
// https-trust-store-type should be automatically set to pkcs12 in fips-mode=enabled
|
||||
CLIResult cliResult = dist.run("--verbose", "start", "--fips-mode=enabled", "--https-key-store-password=passwordpassword",
|
||||
"--https-trust-store-file=" + truststorePath, "--https-trust-store-password=passwordpassword");
|
||||
cliResult.assertStarted();
|
||||
});
|
||||
}
|
||||
|
||||
private void runOnFipsEnabledDistribution(KeycloakDistribution dist, Runnable runnable) {
|
||||
installBcFips(dist);
|
||||
runnable.run();
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -979,5 +979,5 @@ For running testsuite with server using BCFIPS approved mode, those additional p
|
|||
```
|
||||
The log should contain `KeycloakFipsSecurityProvider` mentioning "Approved mode". Something like:
|
||||
```
|
||||
KC(BCFIPS version 1.000203 Approved Mode) version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider,
|
||||
KC(BCFIPS version 1.000203 Approved Mode, FIPS-JVM: enabled) version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider,
|
||||
```
|
||||
|
|
|
|||
|
|
@ -327,18 +327,15 @@ public abstract class AbstractQuarkusDeployableContainer implements DeployableCo
|
|||
private void addFipsOptions(List<String> commands) {
|
||||
commands.add("--fips-mode=" + configuration.getFipsMode().toString());
|
||||
|
||||
log.debugf("Keystore file: %s, keystore type: %s, truststore file: %s, truststore type: %s",
|
||||
configuration.getKeystoreFile(), configuration.getKeystoreType(),
|
||||
configuration.getTruststoreFile(), configuration.getTruststoreType());
|
||||
log.debugf("Keystore file: %s, truststore file: %s",
|
||||
configuration.getKeystoreFile(),
|
||||
configuration.getTruststoreFile());
|
||||
commands.add("--https-key-store-file=" + configuration.getKeystoreFile());
|
||||
commands.add("--https-key-store-type=" + configuration.getKeystoreType());
|
||||
commands.add("--https-key-store-password=" + configuration.getKeystorePassword());
|
||||
commands.add("--https-trust-store-file=" + configuration.getTruststoreFile());
|
||||
commands.add("--https-trust-store-type=" + configuration.getTruststoreType());
|
||||
commands.add("--https-trust-store-password=" + configuration.getTruststorePassword());
|
||||
commands.add("--spi-truststore-file-file=" + configuration.getTruststoreFile());
|
||||
commands.add("--spi-truststore-file-password=" + configuration.getTruststorePassword());
|
||||
commands.add("--spi-truststore-file-type=" + configuration.getTruststoreType());
|
||||
|
||||
// BCFIPS approved mode requires passwords of at least 112 bits (14 characters) to be used. To bypass this, we use this by default
|
||||
// as testsuite uses shorter passwords everywhere
|
||||
|
|
|
|||
|
|
@ -29,15 +29,11 @@ public class KeycloakQuarkusConfiguration implements ContainerConfiguration {
|
|||
|
||||
private String keystorePassword = System.getProperty("auth.server.keystore.password");
|
||||
|
||||
private String keystoreType = System.getProperty("auth.server.keystore.type");
|
||||
|
||||
|
||||
private String truststoreFile = System.getProperty("auth.server.truststore");
|
||||
|
||||
private String truststorePassword = System.getProperty("auth.server.truststore.password");
|
||||
|
||||
private String truststoreType = System.getProperty("auth.server.truststore.type");
|
||||
|
||||
private int debugPort = -1;
|
||||
private Path providersPath = Paths.get(System.getProperty("auth.server.home"));
|
||||
private int startupTimeoutInSeconds = 300;
|
||||
|
|
@ -121,14 +117,6 @@ public class KeycloakQuarkusConfiguration implements ContainerConfiguration {
|
|||
this.keystorePassword = keystorePassword;
|
||||
}
|
||||
|
||||
public String getKeystoreType() {
|
||||
return keystoreType;
|
||||
}
|
||||
|
||||
public void setKeystoreType(String keystoreType) {
|
||||
this.keystoreType = keystoreType;
|
||||
}
|
||||
|
||||
public String getTruststoreFile() {
|
||||
return truststoreFile;
|
||||
}
|
||||
|
|
@ -145,14 +133,6 @@ public class KeycloakQuarkusConfiguration implements ContainerConfiguration {
|
|||
this.truststorePassword = truststorePassword;
|
||||
}
|
||||
|
||||
public String getTruststoreType() {
|
||||
return truststoreType;
|
||||
}
|
||||
|
||||
public void setTruststoreType(String truststoreType) {
|
||||
this.truststoreType = truststoreType;
|
||||
}
|
||||
|
||||
public Path getProvidersPath() {
|
||||
return providersPath;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue