diff --git a/.github/scripts/run-fips-it.sh b/.github/scripts/run-fips-it.sh index 47e4d94ea96..7e20500a0c8 100755 --- a/.github/scripts/run-fips-it.sh +++ b/.github/scripts/run-fips-it.sh @@ -2,9 +2,9 @@ set -x rm -f /etc/system-fips -dnf install -y java-21-openjdk-devel +dnf install -y java-25-openjdk-devel fips-mode-setup --enable --no-bootcfg -fips-mode-setup --is-enabled +fips-mode-setup --check | grep "FIPS mode is enabled." if [ $? -ne 0 ]; then exit 1 fi @@ -16,8 +16,12 @@ if [ "$1" = "strict" ]; then fi echo "STRICT_OPTIONS: $STRICT_OPTIONS" TESTS=`testsuite/integration-arquillian/tests/base/testsuites/suite.sh fips` +if [ $? -ne 0 ]; then + echo "Invalid tests to execute: $TESTS" + exit 1 +fi echo "Tests: $TESTS" -export JAVA_HOME=/etc/alternatives/java_sdk_21 +export JAVA_HOME=/etc/alternatives/java_sdk_25 set -o pipefail # Build adapter distributions @@ -39,7 +43,10 @@ if [ $? -ne 0 ]; then fi # Profile app-server-wildfly needs to be explicitly set for FIPS tests -./mvnw test -Dsurefire.rerunFailingTestsCount=$SUREFIRE_RERUN_FAILING_COUNT -nsu -B -Pauth-server-quarkus,auth-server-fips140-2,app-server-wildfly -Dcom.redhat.fips=false $STRICT_OPTIONS -Dtest=$TESTS -pl testsuite/integration-arquillian/tests/base 2>&1 | misc/log/trimmer.sh +./mvnw test -Dsurefire.rerunFailingTestsCount=$SUREFIRE_RERUN_FAILING_COUNT -nsu -B -Pauth-server-quarkus,auth-server-fips140-2,app-server-wildfly -Dredhat.crypto-policies=false $STRICT_OPTIONS -Dtest=$TESTS -pl testsuite/integration-arquillian/tests/base 2>&1 | misc/log/trimmer.sh +if [ $? -ne 0 ]; then + exit 1 +fi # New Base Tests -./mvnw package -nsu -B -Dcom.redhat.fips=false -Dtest=$TESTSUITE_NAME -pl tests/base +./mvnw package -nsu -B -Dredhat.crypto-policies=false -Dtest=$TESTSUITE_NAME -pl tests/base diff --git a/.github/scripts/run-fips-ut.sh b/.github/scripts/run-fips-ut.sh index 5313c9c7195..8587adc726e 100755 --- a/.github/scripts/run-fips-ut.sh +++ b/.github/scripts/run-fips-ut.sh @@ -1,19 +1,20 @@ #!/usr/bin/env bash rm -f /etc/system-fips -dnf install -y java-21-openjdk-devel crypto-policies-scripts +dnf install -y java-25-openjdk-devel crypto-policies-scripts fips-mode-setup --enable --no-bootcfg -fips-mode-setup --is-enabled +fips-mode-setup --check | grep "FIPS mode is enabled." if [ $? -ne 0 ]; then exit 1 fi -export JAVA_HOME=/etc/alternatives/java_sdk_21 +export JAVA_HOME=/etc/alternatives/java_sdk_25 # Build all dependent modules ./mvnw install -nsu -B -am -pl crypto/default,crypto/fips1402 -DskipTests -./mvnw test -nsu -B -pl crypto/default,crypto/fips1402 -Dcom.redhat.fips=true +./mvnw test -nsu -B -pl crypto/default,crypto/fips1402 -Dredhat.crypto-policies=true if [ $? -ne 0 ]; then exit 1 fi -./mvnw test -nsu -B -pl crypto/default,crypto/fips1402 -Dcom.redhat.fips=true -Dorg.bouncycastle.fips.approved_only=true + +./mvnw test -nsu -B -pl crypto/default,crypto/fips1402 -Dredhat.crypto-policies=true -Dorg.bouncycastle.fips.approved_only=true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8534d203f55..85c0166dbc4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -975,7 +975,7 @@ jobs: sudo insmod fake_fips.ko - name: Run crypto tests - run: docker run --rm --workdir /github/workspace -v "${{ github.workspace }}":"/github/workspace" -v "$HOME/.m2":"/root/.m2" registry.access.redhat.com/ubi8/ubi:latest .github/scripts/run-fips-ut.sh + run: docker run --rm --workdir /github/workspace -v "${{ github.workspace }}":"/github/workspace" -v "$HOME/.m2":"/root/.m2" registry.access.redhat.com/ubi9/ubi:latest .github/scripts/run-fips-ut.sh fips-integration-tests: name: FIPS IT @@ -1002,7 +1002,7 @@ jobs: sudo insmod fake_fips.ko - name: Run base tests - run: docker run --rm --workdir /github/workspace -e "SUREFIRE_RERUN_FAILING_COUNT" -v "${{ github.workspace }}":"/github/workspace" -v "$HOME/.m2":"/root/.m2" registry.access.redhat.com/ubi8/ubi:latest .github/scripts/run-fips-it.sh ${{ matrix.mode }} + run: docker run --rm --workdir /github/workspace -e "SUREFIRE_RERUN_FAILING_COUNT" -v "${{ github.workspace }}":"/github/workspace" -v "$HOME/.m2":"/root/.m2" registry.access.redhat.com/ubi9/ubi:latest .github/scripts/run-fips-it.sh ${{ matrix.mode }} - uses: ./.github/actions/upload-flaky-tests name: Upload flaky tests diff --git a/crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java b/crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java index 561724fbfd0..836b7295550 100644 --- a/crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java +++ b/crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java @@ -1,12 +1,14 @@ package org.keycloak.crypto.fips; import java.io.IOException; -import java.lang.reflect.Method; +import java.io.InputStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import java.net.UnknownHostException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.InvalidAlgorithmParameterException; import java.security.KeyFactory; import java.security.KeyPairGenerator; @@ -34,6 +36,7 @@ import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Pattern; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKeyFactory; @@ -75,6 +78,9 @@ import org.jboss.logging.Logger; public class FIPS1402Provider implements CryptoProvider { private static final Logger log = Logger.getLogger(FIPS1402Provider.class); + private static final String FIPS_FILE = "/proc/sys/crypto/fips_enabled"; + // The fips provider is different in 21 and 25 + private static final String PKCS11_FIPS_NAME = "SunPKCS11(-NSS)?-FIPS"; private final BouncyCastleFipsProvider bcFipsProvider; private final Map providers = new ConcurrentHashMap<>(); @@ -94,19 +100,19 @@ public class FIPS1402Provider implements CryptoProvider { providers.put(CryptoConstants.ECDH_ES_A256KW, new BCFIPSEcdhEsAlgorithmProvider()); if (existingBcFipsProvider == null) { + final String isSystemFipsEnabled = isSystemFipsEnabled(); checkSecureRandom(() -> Security.insertProviderAt(this.bcFipsProvider, 1)); Provider bcJsseProvider = new BouncyCastleJsseProvider("fips:BCFIPS"); Security.insertProviderAt(bcJsseProvider, 2); // force the key and trust manager factories if default values not present in BCJSSE modifyKeyTrustManagerSecurityProperties(bcJsseProvider); + log.infof("FIPS1402Provider created: KC(%s%s, FIPS-JVM: %s)", bcFipsProvider, + CryptoServicesRegistrar.isInApprovedOnlyMode() ? " Approved Mode" : "", + isSystemFipsEnabled); log.debugf("Inserted security providers: %s", Arrays.asList(this.bcFipsProvider.getName(),bcJsseProvider.getName())); } else { log.debugf("Security provider %s already loaded", existingBcFipsProvider.getName()); } - - log.infof("FIPS1402Provider created: KC(%s%s, FIPS-JVM: %s)", bcFipsProvider, - CryptoServicesRegistrar.isInApprovedOnlyMode() ? " Approved Mode" : "", - isSystemFipsEnabled()); } @@ -395,21 +401,14 @@ public class FIPS1402Provider implements CryptoProvider { } public static String isSystemFipsEnabled() { - Method isSystemFipsEnabled = null; - - try { - Class securityConfigurator = FIPS1402Provider.class.getClassLoader().loadClass("java.security.SystemConfigurator"); - isSystemFipsEnabled = securityConfigurator.getDeclaredMethod("isSystemFipsEnabled"); - isSystemFipsEnabled.setAccessible(true); - boolean isEnabled = (boolean) isSystemFipsEnabled.invoke(null); - return isEnabled ? "enabled" : "disabled"; + // java 25 does not have any class and checks directly the file + // check kernel file is 1 and the first security provider is the FIPS one + try (InputStream is = Files.newInputStream(Paths.get(FIPS_FILE))) { + final String name = Security.getProviders()[0].getName(); + return is.read() == '1' && Pattern.matches(PKCS11_FIPS_NAME, name) ? "enabled" : "disabled"; } catch (Throwable ignore) { log.debug("Could not detect if FIPS is enabled from the host", ignore); return "unknown"; - } finally { - if (isSystemFipsEnabled != null) { - isSystemFipsEnabled.setAccessible(false); - } } } } diff --git a/integration/client-cli/admin-cli/src/main/bin/kcadm.sh b/integration/client-cli/admin-cli/src/main/bin/kcadm.sh index 35aa7a1eb1c..92d554686f3 100755 --- a/integration/client-cli/admin-cli/src/main/bin/kcadm.sh +++ b/integration/client-cli/admin-cli/src/main/bin/kcadm.sh @@ -125,4 +125,4 @@ FISH_COMPLETION exit 0 fi -exec "$JAVA" $KC_OPTS -cp $DIRNAME/client/keycloak-admin-cli-${project.version}.jar --add-opens=java.base/java.security=ALL-UNNAMED -Dkc.lib.dir=$DIRNAME/client/lib org.keycloak.client.admin.cli.KcAdmMain "$@" +exec "$JAVA" $KC_OPTS -cp $DIRNAME/client/keycloak-admin-cli-${project.version}.jar --add-opens=java.base/java.security=ALL-UNNAMED --enable-native-access=ALL-UNNAMED -Dkc.lib.dir=$DIRNAME/client/lib org.keycloak.client.admin.cli.KcAdmMain "$@" diff --git a/integration/client-cli/admin-cli/src/main/bin/kcreg.sh b/integration/client-cli/admin-cli/src/main/bin/kcreg.sh index be65bcadb11..8fd510f9132 100755 --- a/integration/client-cli/admin-cli/src/main/bin/kcreg.sh +++ b/integration/client-cli/admin-cli/src/main/bin/kcreg.sh @@ -27,4 +27,4 @@ if [ -z "$JAVA" ]; then fi DIRNAME="$(dirname "$RESOLVED_NAME")" -exec "$JAVA" $KC_OPTS -cp $DIRNAME/client/keycloak-admin-cli-${project.version}.jar --add-opens=java.base/java.security=ALL-UNNAMED -Dkc.lib.dir=$DIRNAME/client/lib org.keycloak.client.registration.cli.KcRegMain "$@" +exec "$JAVA" $KC_OPTS -cp $DIRNAME/client/keycloak-admin-cli-${project.version}.jar --add-opens=java.base/java.security=ALL-UNNAMED --enable-native-access=ALL-UNNAMED -Dkc.lib.dir=$DIRNAME/client/lib org.keycloak.client.registration.cli.KcRegMain "$@" diff --git a/testsuite/integration-arquillian/tests/base/testsuites/fips-suite b/testsuite/integration-arquillian/tests/base/testsuites/fips-suite index 82575a3322f..a52e2fc66fb 100644 --- a/testsuite/integration-arquillian/tests/base/testsuites/fips-suite +++ b/testsuite/integration-arquillian/tests/base/testsuites/fips-suite @@ -32,7 +32,4 @@ KcSamlSignedBrokerTest KcSamlSpDescriptorTest KerberosLdapTest TrustStoreEmailTest -OID4VCJWTIssuerEndpointTest OID4VCSdJwtIssuingEndpointTest -OID4VCJwtAuthorizationCodeFlowTest -OID4VCSdJwtAuthorizationCodeFlowTest