From 768cea1b82e070f53ab06a06a4383d6dc2f19391 Mon Sep 17 00:00:00 2001 From: Lukas Hanusovsky <61745358+lhanusov@users.noreply.github.com> Date: Thu, 6 Nov 2025 14:08:19 +0100 Subject: [PATCH] Add FIPS suite to the new tests (#43431) * Add FIPS test suite to the new tests Signed-off-by: Lukas Hanusovsky * Tweaks to FIPS suite in new test Signed-off-by: stianst --------- Signed-off-by: Lukas Hanusovsky Signed-off-by: stianst Co-authored-by: stianst --- .github/scripts/run-fips-it.sh | 5 + .../src/main/java/org/keycloak/Keycloak.java | 15 +- .../CoreTestFrameworkExtension.java | 4 +- .../https/CertificatesConfig.java | 6 + .../https/CertificatesConfigBuilder.java | 20 ++ .../https/CertificatesSupplier.java | 13 +- .../https/DefaultCertificatesConfig.java | 9 + .../https/InjectCertificates.java | 2 + .../https/ManagedCertificates.java | 52 ++-- .../testframework/injection/SuiteSupport.java | 10 +- .../server/KeycloakServerConfigBuilder.java | 3 +- tests/FIPS_104-2.md | 26 ++ .../keycloak/tests}/admin/ServerInfoTest.java | 43 +-- .../tests/admin/client/CredentialsTest.java | 273 ++++++++++++++++++ .../admin/realm/RealmDefaultConfigTest.java | 5 +- .../tests/suites/FipsNonStrictTestSuite.java | 53 ++++ .../tests/suites/FipsStrictTestSuite.java | 56 ++++ .../keycloak/tests/suites/JDKTestSuite.java | 5 +- .../org/keycloak/tests/utils/FipsUtils.java | 32 ++ .../admin/GenerateKeystoreForTestUtil.java | 67 +++++ .../admin/client/CredentialsTest.java | 259 ----------------- .../tests/base/testsuites/fips-suite | 2 - .../tests/base/testsuites/jdk-suite | 1 - 23 files changed, 633 insertions(+), 328 deletions(-) create mode 100644 test-framework/core/src/main/java/org/keycloak/testframework/https/CertificatesConfig.java create mode 100644 test-framework/core/src/main/java/org/keycloak/testframework/https/CertificatesConfigBuilder.java create mode 100644 test-framework/core/src/main/java/org/keycloak/testframework/https/DefaultCertificatesConfig.java create mode 100644 tests/FIPS_104-2.md rename {testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite => tests/base/src/test/java/org/keycloak/tests}/admin/ServerInfoTest.java (78%) create mode 100644 tests/base/src/test/java/org/keycloak/tests/admin/client/CredentialsTest.java create mode 100644 tests/base/src/test/java/org/keycloak/tests/suites/FipsNonStrictTestSuite.java create mode 100644 tests/base/src/test/java/org/keycloak/tests/suites/FipsStrictTestSuite.java create mode 100644 tests/utils/src/main/java/org/keycloak/tests/utils/FipsUtils.java create mode 100644 tests/utils/src/main/java/org/keycloak/tests/utils/admin/GenerateKeystoreForTestUtil.java delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/CredentialsTest.java diff --git a/.github/scripts/run-fips-it.sh b/.github/scripts/run-fips-it.sh index b0cfe748e7a..5b6405b359c 100755 --- a/.github/scripts/run-fips-it.sh +++ b/.github/scripts/run-fips-it.sh @@ -8,8 +8,10 @@ if [ $? -ne 0 ]; then exit 1 fi STRICT_OPTIONS="" +TESTSUITE_NAME="FipsNonStrictTestSuite" if [ "$1" = "strict" ]; then STRICT_OPTIONS="-Dauth.server.fips.mode=strict -Dauth.server.supported.keystore.types=BCFKS -Dauth.server.keystore.type=bcfks -Dauth.server.supported.rsa.key.sizes=2048,3072,4096" + TESTSUITE_NAME="FipsStrictTestSuite" fi echo "STRICT_OPTIONS: $STRICT_OPTIONS" TESTS=`testsuite/integration-arquillian/tests/base/testsuites/suite.sh fips` @@ -37,3 +39,6 @@ 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 + +# New Base Tests +./mvnw package -nsu -B -Dcom.redhat.fips=false -Dtest=$TESTSUITE_NAME -pl tests/base diff --git a/quarkus/tests/junit5/src/main/java/org/keycloak/Keycloak.java b/quarkus/tests/junit5/src/main/java/org/keycloak/Keycloak.java index aa05646fd64..011a1468622 100644 --- a/quarkus/tests/junit5/src/main/java/org/keycloak/Keycloak.java +++ b/quarkus/tests/junit5/src/main/java/org/keycloak/Keycloak.java @@ -55,6 +55,7 @@ import io.quarkus.bootstrap.workspace.WorkspaceModuleId; import io.quarkus.maven.dependency.Dependency; import io.quarkus.maven.dependency.DependencyBuilder; import io.quarkus.runtime.configuration.QuarkusConfigFactory; +import org.keycloak.quarkus.runtime.configuration.IgnoredArtifacts; public class Keycloak { @@ -123,7 +124,7 @@ public class Keycloak { addOptionIfNotSet(args, HttpOptions.HTTP_PORT); addOptionIfNotSet(args, HttpOptions.HTTPS_PORT); - boolean isFipsEnabled = ofNullable(getOptionValue(args, SecurityOptions.FIPS_MODE)).map(FipsMode::valueOf).orElse(FipsMode.DISABLED).isFipsEnabled(); + boolean isFipsEnabled = ofNullable(getOptionValue(args, SecurityOptions.FIPS_MODE)).map(FipsMode::valueOfOption).orElse(FipsMode.DISABLED).isFipsEnabled(); if (isFipsEnabled) { String logLevel = getOptionValue(args, LoggingOptions.LOG_LEVEL); @@ -241,11 +242,9 @@ public class Keycloak { .addExclusion("org.jboss.logmanager", "log4j-jboss-logmanager"); if (fipsEnabled) { - serverDependency.addExclusion("org.bouncycastle", "bcprov-jdk18on"); - serverDependency.addExclusion("org.bouncycastle", "bcpkix-jdk18on"); - serverDependency.addExclusion("org.keycloak", "keycloak-crypto-default"); + IgnoredArtifacts.FIPS_ENABLED.stream().map(s -> s.split(":")).forEach(d -> serverDependency.addExclusion(d[0], d[1])); } else { - serverDependency.addExclusion("org.keycloak", "keycloak-crypto-fips1402"); + IgnoredArtifacts.FIPS_DISABLED.stream().map(s -> s.split(":")).forEach(d -> serverDependency.addExclusion(d[0], d[1])); } WorkspaceModule.Mutable builder = WorkspaceModule.builder() @@ -256,12 +255,6 @@ public class Keycloak { Dependency.pomImport("org.keycloak", "keycloak-quarkus-parent", keycloakVersion)) .addDependency(serverDependency.build()); - if (fipsEnabled) { - builder.addDependency(Dependency.of("org.bouncycastle", "bc-fips")); - builder.addDependency(Dependency.of("org.bouncycastle", "bctls-fips")); - builder.addDependency(Dependency.of("org.bouncycastle", "bcpkix-fips")); - } - for (Dependency dependency : dependencies) { builder.addDependency(dependency); } diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/CoreTestFrameworkExtension.java b/test-framework/core/src/main/java/org/keycloak/testframework/CoreTestFrameworkExtension.java index 19b38dc283f..6d0c93a8b69 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/CoreTestFrameworkExtension.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/CoreTestFrameworkExtension.java @@ -3,6 +3,7 @@ package org.keycloak.testframework; import org.keycloak.testframework.admin.AdminClientFactorySupplier; import org.keycloak.testframework.admin.AdminClientSupplier; import org.keycloak.testframework.http.SimpleHttpSupplier; +import org.keycloak.testframework.https.ManagedCertificates; import org.keycloak.testframework.infinispan.InfinispanExternalServerSupplier; import org.keycloak.testframework.database.DevFileDatabaseSupplier; import org.keycloak.testframework.database.DevMemDatabaseSupplier; @@ -57,7 +58,8 @@ public class CoreTestFrameworkExtension implements TestFrameworkExtension { public Map, String> valueTypeAliases() { return Map.of( KeycloakServer.class, "server", - TestDatabase.class, "database" + TestDatabase.class, "database", + ManagedCertificates.class, "certificates" ); } diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/https/CertificatesConfig.java b/test-framework/core/src/main/java/org/keycloak/testframework/https/CertificatesConfig.java new file mode 100644 index 00000000000..666b3529b19 --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/testframework/https/CertificatesConfig.java @@ -0,0 +1,6 @@ +package org.keycloak.testframework.https; + +public interface CertificatesConfig { + + CertificatesConfigBuilder configure(CertificatesConfigBuilder config); +} diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/https/CertificatesConfigBuilder.java b/test-framework/core/src/main/java/org/keycloak/testframework/https/CertificatesConfigBuilder.java new file mode 100644 index 00000000000..18516902ddb --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/testframework/https/CertificatesConfigBuilder.java @@ -0,0 +1,20 @@ +package org.keycloak.testframework.https; + +import org.keycloak.common.util.KeystoreUtil; + +public class CertificatesConfigBuilder { + + private KeystoreUtil.KeystoreFormat keystoreFormat = KeystoreUtil.KeystoreFormat.JKS; + + public CertificatesConfigBuilder() { + } + + public CertificatesConfigBuilder keystoreFormat(KeystoreUtil.KeystoreFormat keystoreFormat) { + this.keystoreFormat = keystoreFormat; + return this; + } + + public KeystoreUtil.KeystoreFormat getKeystoreFormat() { + return this.keystoreFormat; + } +} diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/https/CertificatesSupplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/https/CertificatesSupplier.java index 0320c5aad7a..fe510b89f23 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/https/CertificatesSupplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/https/CertificatesSupplier.java @@ -1,16 +1,27 @@ package org.keycloak.testframework.https; +import org.keycloak.testframework.config.Config; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.LifeCycle; import org.keycloak.testframework.injection.RequestedInstance; import org.keycloak.testframework.injection.Supplier; +import org.keycloak.testframework.injection.SupplierHelpers; import org.keycloak.testframework.injection.SupplierOrder; public class CertificatesSupplier implements Supplier { @Override public ManagedCertificates getValue(InstanceContext instanceContext) { - return new ManagedCertificates(); + CertificatesConfig certConfig = SupplierHelpers.getInstance(instanceContext.getAnnotation().config()); + CertificatesConfigBuilder certBuilder = new CertificatesConfigBuilder(); + certBuilder = certConfig.configure(certBuilder); + + String supplierConfig = Config.getSupplierConfig(ManagedCertificates.class); + if (supplierConfig != null) { + CertificatesConfig certConfigOverride = SupplierHelpers.getInstance(supplierConfig); + certConfigOverride.configure(certBuilder); + } + return new ManagedCertificates(certBuilder); } @Override diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/https/DefaultCertificatesConfig.java b/test-framework/core/src/main/java/org/keycloak/testframework/https/DefaultCertificatesConfig.java new file mode 100644 index 00000000000..f7456e71490 --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/testframework/https/DefaultCertificatesConfig.java @@ -0,0 +1,9 @@ +package org.keycloak.testframework.https; + +public class DefaultCertificatesConfig implements CertificatesConfig { + + @Override + public CertificatesConfigBuilder configure(CertificatesConfigBuilder config) { + return config; + } +} diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/https/InjectCertificates.java b/test-framework/core/src/main/java/org/keycloak/testframework/https/InjectCertificates.java index 8b5a5c29336..87a9346fd5c 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/https/InjectCertificates.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/https/InjectCertificates.java @@ -8,4 +8,6 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface InjectCertificates { + + Class config() default DefaultCertificatesConfig.class; } diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/https/ManagedCertificates.java b/test-framework/core/src/main/java/org/keycloak/testframework/https/ManagedCertificates.java index 4b4e7c39f54..1369f6448af 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/https/ManagedCertificates.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/https/ManagedCertificates.java @@ -30,31 +30,35 @@ public class ManagedCertificates { private KeyStore serverKeyStore; private KeyStore clientsTrustStore; + private final Path serverKeystorePath; + private final Path clientsTruststorePath; + private final char[] password; private final static Path KEYSTORES_DIR = Path.of(System.getProperty("java.io.tmpdir")); - private final static Path SERVER_KEYSTORE_FILE_PATH = KEYSTORES_DIR.resolve("kc-testing-server-keystore.jks"); - private final static Path CLIENTS_TRUSTSTORE_FILE_PATH = KEYSTORES_DIR.resolve("kc-testing-clients-truststore.jks"); - - private final static char[] PASSWORD = "password".toCharArray(); - private final static String PRV_KEY_ENTRY = "prvKey"; public final static String CERT_ENTRY = "cert"; - public ManagedCertificates() throws ManagedCertificatesException { + public ManagedCertificates(CertificatesConfigBuilder configBuilder) throws ManagedCertificatesException { if (!CryptoIntegration.isInitialised()) { CryptoIntegration.setProvider(new DefaultCryptoProvider()); } cryptoProvider = CryptoIntegration.getProvider(); - initServerCerts(); + + serverKeystorePath = KEYSTORES_DIR.resolve("kc-testing-server-keystore" + "." + configBuilder.getKeystoreFormat().getPrimaryExtension()); + clientsTruststorePath = KEYSTORES_DIR.resolve("kc-testing-clients-truststore" + "." + configBuilder.getKeystoreFormat().getPrimaryExtension()); + + password = configBuilder.getKeystoreFormat() == KeystoreUtil.KeystoreFormat.JKS ? "password".toCharArray() : "passwordpassword".toCharArray(); + + initServerCerts(configBuilder.getKeystoreFormat()); } public String getKeycloakServerKeyStorePath() { - return SERVER_KEYSTORE_FILE_PATH.toString(); + return serverKeystorePath.toString(); } public String getKeycloakServerKeyStorePassword() { - return String.valueOf(PASSWORD); + return String.valueOf(password); } public KeyStore getClientTrustStore() { @@ -79,26 +83,26 @@ public class ManagedCertificates { } } - private void initServerCerts() throws ManagedCertificatesException { + private void initServerCerts(KeystoreUtil.KeystoreFormat keystoreFormat) throws ManagedCertificatesException { try { - serverKeyStore = cryptoProvider.getKeyStore(KeystoreUtil.KeystoreFormat.JKS); - clientsTrustStore = cryptoProvider.getKeyStore(KeystoreUtil.KeystoreFormat.JKS); + serverKeyStore = cryptoProvider.getKeyStore(keystoreFormat); + clientsTrustStore = cryptoProvider.getKeyStore(keystoreFormat); - if (Files.exists(SERVER_KEYSTORE_FILE_PATH) && Files.exists(CLIENTS_TRUSTSTORE_FILE_PATH)) { + if (Files.exists(serverKeystorePath) && Files.exists(clientsTruststorePath)) { LOGGER.debugv("Existing Server KeyStore files found in {0}", KEYSTORES_DIR); - loadKeyStore(serverKeyStore, SERVER_KEYSTORE_FILE_PATH, PASSWORD); - loadKeyStore(clientsTrustStore, CLIENTS_TRUSTSTORE_FILE_PATH, PASSWORD); + loadKeyStore(serverKeyStore, serverKeystorePath, password); + loadKeyStore(clientsTrustStore, clientsTruststorePath, password); } else { LOGGER.debugv("Generating Server KeyStore files in {0}", KEYSTORES_DIR); - generateKeystore(serverKeyStore, clientsTrustStore, "localhost"); + generateKeystoreAndTruststore(serverKeyStore, clientsTrustStore, "localhost"); // store the generated keystore and truststore in a temp folder - try (FileOutputStream fos = new FileOutputStream(SERVER_KEYSTORE_FILE_PATH.toFile())) { - serverKeyStore.store(fos, PASSWORD); + try (FileOutputStream fos = new FileOutputStream(serverKeystorePath.toFile())) { + serverKeyStore.store(fos, password); } - try (FileOutputStream fos = new FileOutputStream(CLIENTS_TRUSTSTORE_FILE_PATH.toFile())) { - clientsTrustStore.store(fos, PASSWORD); + try (FileOutputStream fos = new FileOutputStream(clientsTruststorePath.toFile())) { + clientsTrustStore.store(fos, password); } } } catch (Exception e) { @@ -112,7 +116,7 @@ public class ManagedCertificates { } } - private void generateKeystore(KeyStore keyStore, KeyStore trustStore, String subject) throws NoSuchAlgorithmException, NoSuchProviderException, CertificateException, IOException, KeyStoreException, Exception { + private void generateKeystoreAndTruststore(KeyStore keyStore, KeyStore trustStore, String subject) throws NoSuchAlgorithmException, NoSuchProviderException, CertificateException, IOException, KeyStoreException, Exception { keyStore.load(null); trustStore.load(null); @@ -121,7 +125,7 @@ public class ManagedCertificates { keyStore.setCertificateEntry(CERT_ENTRY, cert); trustStore.setCertificateEntry(CERT_ENTRY, cert); - keyStore.setKeyEntry(PRV_KEY_ENTRY, keyPair.getPrivate(), PASSWORD, new X509Certificate[]{cert}); + keyStore.setKeyEntry(PRV_KEY_ENTRY, keyPair.getPrivate(), password, new X509Certificate[]{cert}); } private KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException { @@ -129,10 +133,10 @@ public class ManagedCertificates { } private X509Certificate generateX509CertificateCertificate(KeyPair keyPair, String subject) throws Exception { - // generate a v1 certificate + // generate a v1 root certificate authority certificate X509Certificate caCert = cryptoProvider.getCertificateUtils().generateV1SelfSignedCertificate(keyPair, subject); - // generate a v3 certificate + // generate a v3 certificate chain return cryptoProvider.getCertificateUtils().generateV3Certificate(keyPair, keyPair.getPrivate(), caCert, subject); } } diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/SuiteSupport.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/SuiteSupport.java index eadb1b9305c..b824450c537 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/injection/SuiteSupport.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/SuiteSupport.java @@ -9,6 +9,9 @@ public class SuiteSupport { private static SuiteConfig suiteConfig = new SuiteConfig(); public static SuiteConfig startSuite() { + if (suiteConfig == null) { + suiteConfig = new SuiteConfig(); + } return suiteConfig; } @@ -22,7 +25,12 @@ public class SuiteSupport { public static class SuiteConfig { public SuiteConfig registerServerConfig(Class serverConfig) { - SuiteConfigSource.set("kc.test.server.config", serverConfig.getName()); + registerSupplierConfig("server", serverConfig); + return this; + } + + public SuiteConfig registerSupplierConfig(String supplierValueType, Class supplierConfig) { + SuiteConfigSource.set("kc.test." + supplierValueType + ".config", supplierConfig.getName()); return this; } diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/server/KeycloakServerConfigBuilder.java b/test-framework/core/src/main/java/org/keycloak/testframework/server/KeycloakServerConfigBuilder.java index 541d9ac2a0a..3f0b5a4c557 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/server/KeycloakServerConfigBuilder.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/server/KeycloakServerConfigBuilder.java @@ -115,8 +115,7 @@ public class KeycloakServerConfigBuilder { public boolean tlsEnabled() { return tlsEnabled ; } - - + public KeycloakServerConfigBuilder cacheConfigFile(String resourcePath) { try { Path p = Paths.get(Objects.requireNonNull(getClass().getResource(resourcePath)).toURI()); diff --git a/tests/FIPS_104-2.md b/tests/FIPS_104-2.md new file mode 100644 index 00000000000..7a8180108a8 --- /dev/null +++ b/tests/FIPS_104-2.md @@ -0,0 +1,26 @@ +## FIPS 140-2 testing + +### Integration tests + +On a FIPS enabled platform with FIPS enabled OpenJDK 21, you can run this to test against a Keycloak server with FIPS 140-2 integration enabled. + +``` +./mvnw clean package -nsu -B -f tests/base/pom.xml \ + -Dcom.redhat.fips=false \ + -Dtest=FipsStrictTestSuite,FipsNonStrictTestSuite +``` +FIPS test suite configuration (strict and non-strict): +[FipsStrictTestSuite](./base/src/test/java/org/keycloak/tests/suites/FipsStrictTestSuite.java), +[FipsNonStrictTestSuite](./base/src/test/java/org/keycloak/tests/suites/FipsNonStrictTestSuite.java) + +NOTE 1: The property `com.redhat.fips` is required for disabling FIPS in JVM, on a FIPS enabled environment (operating system or container), where the test suite is executed. + +NOTE 3: Example of the server startup log, running in an environment (both -> JVM and operating system/container), where FIPS is enabled: +``` +2022-10-11 19:34:29,521 DEBUG [org.keycloak.common.crypto.CryptoIntegration] (main) Using the crypto provider: org.keycloak.crypto.fips.FIPS1402Provider +2022-10-11 19:34:31,072 TRACE [org.keycloak.common.crypto.CryptoIntegration] (main) Java security providers: [ + KC(BCFIPS version 1.000203, FIPS-JVM: enabled) version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider, + BCFIPS version 1.000203 - class org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider, + BCJSSE version 1.001202 - class org.bouncycastle.jsse.provider.BouncyCastleJsseProvider, +] +``` \ No newline at end of file diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ServerInfoTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/ServerInfoTest.java similarity index 78% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ServerInfoTest.java rename to tests/base/src/test/java/org/keycloak/tests/admin/ServerInfoTest.java index 55b1db2f64b..39cff5b3e42 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ServerInfoTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/ServerInfoTest.java @@ -15,9 +15,11 @@ * limitations under the License. */ -package org.keycloak.testsuite.admin; +package org.keycloak.tests.admin; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.keycloak.admin.client.Keycloak; import org.keycloak.common.Version; import org.keycloak.crypto.Algorithm; import org.keycloak.keys.Attributes; @@ -25,24 +27,26 @@ import org.keycloak.keys.GeneratedRsaKeyProviderFactory; import org.keycloak.keys.KeyProvider; import org.keycloak.representations.idm.ComponentTypeRepresentation; import org.keycloak.representations.idm.ConfigPropertyRepresentation; -import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.info.ProviderRepresentation; import org.keycloak.representations.info.ServerInfoRepresentation; -import org.keycloak.testsuite.AbstractKeycloakTest; -import org.keycloak.testsuite.Assert; -import org.keycloak.testsuite.util.KeyUtils; -import org.keycloak.testsuite.util.KeystoreUtils; +import org.keycloak.testframework.annotations.InjectAdminClient; +import org.keycloak.testframework.annotations.KeycloakIntegrationTest; +import org.keycloak.tests.utils.Assert; +import org.keycloak.tests.utils.FipsUtils; -import java.util.List; import java.util.Map; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; /** * @author Stian Thorgersen */ -public class ServerInfoTest extends AbstractKeycloakTest { +@KeycloakIntegrationTest +public class ServerInfoTest { + + @InjectAdminClient + Keycloak adminClient; @Test public void testServerInfo() { @@ -56,18 +60,21 @@ public class ServerInfoTest extends AbstractKeycloakTest { assertNotNull(info.getThemes()); assertNotNull(info.getThemes().get("account")); - Assert.assertNames(info.getThemes().get("account"), "base", "keycloak.v3", "custom-account-provider"); + Assert.assertNames(info.getThemes().get("account"), "base", "keycloak.v3"); Assert.assertNames(info.getThemes().get("admin"), "base", "keycloak.v2"); Assert.assertNames(info.getThemes().get("email"), "base", "keycloak"); - Assert.assertNames(info.getThemes().get("login"), "address", "base", "environment-agnostic", "keycloak", "keycloak.v2", "organization", "themeconfig"); + Assert.assertNames(info.getThemes().get("login"), "base", "keycloak", "keycloak.v2"); Assert.assertNames(info.getThemes().get("welcome"), "keycloak"); assertNotNull(info.getEnums()); assertNotNull(info.getMemoryInfo()); assertNotNull(info.getSystemInfo()); + + FipsUtils fipsUtils = FipsUtils.create(info); + assertNotNull(info.getCryptoInfo()); - Assert.assertNames(info.getCryptoInfo().getSupportedKeystoreTypes(), KeystoreUtils.getSupportedKeystoreTypes()); + Assert.assertNames(info.getCryptoInfo().getSupportedKeystoreTypes(), fipsUtils.getExpectedSupportedKeyStoreTypes()); Assert.assertNames(info.getCryptoInfo().getClientSignatureSymmetricAlgorithms(), Algorithm.HS256, Algorithm.HS384, Algorithm.HS512); Assert.assertNames(info.getCryptoInfo().getClientSignatureAsymmetricAlgorithms(), Algorithm.ES256, Algorithm.ES384, Algorithm.ES512, @@ -83,7 +90,7 @@ public class ServerInfoTest extends AbstractKeycloakTest { .stream() .filter(configProp -> Attributes.KEY_SIZE_KEY.equals(configProp.getName())) .findFirst().orElseThrow(() -> new RuntimeException("Not found provider with ID 'rsa-generated'")); - Assert.assertNames(keySizeRep.getOptions(), KeyUtils.getExpectedSupportedRsaKeySizes()); + Assert.assertNames(keySizeRep.getOptions(), fipsUtils.getExpectedSupportedRsaKeySizes()); assertEquals(Version.VERSION, info.getSystemInfo().getVersion()); assertNotNull(info.getSystemInfo().getServerTime()); @@ -91,10 +98,6 @@ public class ServerInfoTest extends AbstractKeycloakTest { Map jpaProviders = info.getProviders().get("connectionsJpa").getProviders(); ProviderRepresentation jpaProvider = jpaProviders.values().iterator().next(); - log.infof("JPA Connections provider info: %s", jpaProvider.getOperationalInfo()); - } - - @Override - public void addTestRealms(List testRealms) { + Assertions.assertNotNull(jpaProvider.getOperationalInfo()); } } diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/client/CredentialsTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/client/CredentialsTest.java new file mode 100644 index 00000000000..f1a42ed24aa --- /dev/null +++ b/tests/base/src/test/java/org/keycloak/tests/admin/client/CredentialsTest.java @@ -0,0 +1,273 @@ +/* + * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @author tags. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package org.keycloak.tests.admin.client; + +import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.keycloak.admin.client.Keycloak; +import org.keycloak.admin.client.resource.ClientAttributeCertificateResource; +import org.keycloak.common.crypto.CryptoIntegration; +import org.keycloak.common.util.KeystoreUtil; +import org.keycloak.common.util.PemUtils; +import org.keycloak.crypto.def.DefaultCryptoProvider; +import org.keycloak.events.admin.OperationType; +import org.keycloak.events.admin.ResourceType; +import org.keycloak.models.utils.KeycloakModelUtils; +import org.keycloak.representations.KeyStoreConfig; +import org.keycloak.representations.idm.CertificateRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.CredentialRepresentation; +import org.keycloak.testframework.annotations.InjectAdminClient; +import org.keycloak.testframework.annotations.InjectAdminEvents; +import org.keycloak.testframework.annotations.InjectClient; +import org.keycloak.testframework.annotations.InjectRealm; +import org.keycloak.testframework.annotations.KeycloakIntegrationTest; +import org.keycloak.testframework.events.AdminEventAssertion; +import org.keycloak.testframework.events.AdminEvents; +import org.keycloak.testframework.realm.ManagedClient; +import org.keycloak.testframework.realm.ManagedRealm; +import org.keycloak.tests.utils.admin.AdminEventPaths; + +import jakarta.ws.rs.core.MediaType; +import org.keycloak.tests.utils.admin.GenerateKeystoreForTestUtil; + +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** + * + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ +@KeycloakIntegrationTest +public class CredentialsTest { + + @InjectRealm + ManagedRealm managedRealm; + + @InjectAdminClient + Keycloak adminClient; + + @InjectClient(attachTo = "account") + ManagedClient managedClient; + + @InjectAdminEvents + AdminEvents adminEvents; + + @BeforeAll + public static void init() { + if(!CryptoIntegration.isInitialised()) { + CryptoIntegration.setProvider(new DefaultCryptoProvider()); + } + } + + @Test + public void testGetAndRegenerateSecret() { + CredentialRepresentation oldCredential = managedClient.admin().getSecret(); + CredentialRepresentation newCredential = managedClient.admin().generateNewSecret(); + + CredentialRepresentation secretRep = new CredentialRepresentation(); + secretRep.setType(CredentialRepresentation.SECRET); + AdminEventAssertion.assertEvent(adminEvents.poll(), OperationType.ACTION, AdminEventPaths.clientGenerateSecretPath(managedClient.getId()), secretRep, ResourceType.CLIENT); + + assertNotNull(oldCredential); + assertNotNull(newCredential); + assertNotEquals(newCredential.getValue(), oldCredential.getValue()); + assertEquals(newCredential.getValue(), managedClient.admin().getSecret().getValue()); + } + + @Test + public void testGetAndRegenerateRegistrationAccessToken() { + ClientRepresentation rep = managedClient.admin().toRepresentation(); + String oldToken = rep.getRegistrationAccessToken(); + String newToken = managedClient.admin().regenerateRegistrationAccessToken().getRegistrationAccessToken(); + assertNull(oldToken); // registration access token not saved in ClientRep + assertNotNull(newToken); // it's only available via regenerateRegistrationAccessToken() + assertNull(managedClient.admin().toRepresentation().getRegistrationAccessToken()); + + // Test event + ClientRepresentation testedRep = new ClientRepresentation(); + testedRep.setClientId(rep.getClientId()); + testedRep.setRegistrationAccessToken(newToken); + AdminEventAssertion.assertEvent(adminEvents.poll(), OperationType.ACTION, AdminEventPaths.clientRegenerateRegistrationAccessTokenPath(managedClient.getId()), testedRep, ResourceType.CLIENT); + } + + @Test + public void testGetCertificateResource() { + ClientAttributeCertificateResource certRsc = managedClient.admin().getCertficateResource("jwt.credential"); + CertificateRepresentation cert = certRsc.generate(); + CertificateRepresentation certFromGet = certRsc.getKeyInfo(); + assertEquals(cert.getCertificate(), certFromGet.getCertificate()); + assertEquals(cert.getPrivateKey(), certFromGet.getPrivateKey()); + + AdminEventAssertion.assertEvent(adminEvents.poll(), OperationType.ACTION, AdminEventPaths.clientCertificateGenerateSecretPath(managedClient.getId(), "jwt.credential"), cert, ResourceType.CLIENT); + } + + @Test + public void testUploadKeyAndCertificate() throws Exception { + String certificate2 = "MIICnTCCAYUCBgFPPQDGxTANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdjbGllbnQxMB4XDTE1MDgxNzE4NTAwNVoXDTI1MDgxNzE4NTE0NVowEjEQMA4GA1UEAwwHY2xpZW50MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMMw3PaBffWxgS2PYSDDBp6As+cNvv9kt2C4f/RDAGmvSIHPFev9kuQiKs3Oaws3ZsV4JG3qHEuYgnh9W4vfe3DwNwtD1bjL5FYBhPBFTw0lAQECYxaBHnkjHwUKp957FqdSPPICm3LjmTcEdlH+9dpp9xHCMbbiNiWDzWI1xSxC8Fs2d0hwz1sd+Q4QeTBPIBWcPM+ICZtNG5MN+ORfayu4X+Me5d0tXG2fQO//rAevk1i5IFjKZuOjTwyKB5SJIY4b8QTeg0g/50IU7Ht00Pxw6CK02dHS+FvXHasZlD3ckomqCDjStTBWdhJo5dST0CbOqalkkpLlCCbGA1yEQRsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAUIMeJ+EAo8eNpCG/nXImacjrKakbFnZYBGD/gqeTGaZynkX+jgBSructTHR83zSH+yELEhsAy+3BfK4EEihp+PEcRnK2fASVkHste8AQ7rlzC+HGGirlwrVhWCdizNUCGK80DE537IZ7nmZw6LFG9P5/Q2MvCsOCYjRUvMkukq6TdXBXR9tETwZ+0gpSfsOxjj0ZF7ftTRUSzx4rFfcbM9fRNdVizdOuKGc8HJPA5lLOxV6CyaYIvi3y5RlQI1OHeS34lE4w9CNPRFa/vdxXvN7ClyzA0HMFNWxBN7pC/Ht/FbhSvaAagJBHg+vCrcY5C26Oli7lAglf/zZrwUPs0w=="; + + ClientAttributeCertificateResource certRsc = managedClient.admin().getCertficateResource("jwt.credential"); + + KeystoreUtil.KeystoreFormat preferredKeystoreType = KeystoreUtil.KeystoreFormat.valueOf(adminClient.serverInfo().getInfo().getCryptoInfo().getSupportedKeystoreTypes().get(0)); + + // Generate keystore file and upload privateKey and certificate from it as JKS store (or eventually PKCS12 or BCFKS store according to which one is preferred type) + GenerateKeystoreForTestUtil.KeystoreInfo generatedKeystore = GenerateKeystoreForTestUtil.generateKeystore(preferredKeystoreType, "clientkey", "storepass", "keypass"); + MultipartFormDataOutput keyCertForm = new MultipartFormDataOutput(); + + keyCertForm.addFormData("keystoreFormat", preferredKeystoreType.toString(), MediaType.TEXT_PLAIN_TYPE); + keyCertForm.addFormData("keyAlias", "clientkey", MediaType.TEXT_PLAIN_TYPE); + keyCertForm.addFormData("keyPassword", "keypass", MediaType.TEXT_PLAIN_TYPE); + keyCertForm.addFormData("storePassword", "storepass", MediaType.TEXT_PLAIN_TYPE); + + FileInputStream fs = new FileInputStream(generatedKeystore.getKeystoreFile()); + byte [] content = fs.readAllBytes(); + fs.close(); + keyCertForm.addFormData("file", content, MediaType.APPLICATION_OCTET_STREAM_TYPE); + CertificateRepresentation cert = certRsc.uploadJks(keyCertForm); + + // Returned cert is not the new state but rather what was extracted from inputs + assertNotNull(cert, "cert not null"); + assertEquals(generatedKeystore.getCertificateInfo().getCertificate(), cert.getCertificate(), "cert properly extracted"); + assertEquals(generatedKeystore.getCertificateInfo().getPrivateKey(), cert.getPrivateKey(), "privateKey properly extracted"); + + // Get the certificate - to make sure cert was properly updated + cert = certRsc.getKeyInfo(); + assertEquals(generatedKeystore.getCertificateInfo().getCertificate(), cert.getCertificate(), "cert properly set"); + assertEquals(generatedKeystore.getCertificateInfo().getPrivateKey(), cert.getPrivateKey(), "privateKey properly set"); + + // Upload a different certificate via /upload-certificate, privateKey should be nullified + MultipartFormDataOutput form = new MultipartFormDataOutput(); + form.addFormData("keystoreFormat", "Certificate PEM", MediaType.TEXT_PLAIN_TYPE); + form.addFormData("file", certificate2.getBytes(StandardCharsets.US_ASCII), MediaType.APPLICATION_OCTET_STREAM_TYPE); + cert = certRsc.uploadJksCertificate(form); + assertNotNull(cert, "cert not null"); + assertEquals(certificate2, cert.getCertificate(), "cert properly extracted"); + assertNull(cert.getPrivateKey(), "privateKey not included"); + + // Get the certificate - to make sure cert was properly updated, and privateKey is null + cert = certRsc.getKeyInfo(); + assertEquals(certificate2, cert.getCertificate(), "cert properly set"); + assertNull(cert.getPrivateKey(), "privateKey nullified"); + + // Re-upload the private key + certRsc.uploadJks(keyCertForm); + + // Upload certificate as PEM via /upload - nullifies the private key + form = new MultipartFormDataOutput(); + form.addFormData("keystoreFormat", "Certificate PEM", MediaType.TEXT_PLAIN_TYPE); + form.addFormData("file", certificate2.getBytes(StandardCharsets.US_ASCII), MediaType.APPLICATION_OCTET_STREAM_TYPE); + cert = certRsc.uploadJks(form); + assertNotNull(cert, "cert not null"); + assertEquals(certificate2, cert.getCertificate(), "cert properly extracted"); + assertNull(cert.getPrivateKey(), "privateKey not included"); + + // Get the certificate again - to make sure cert is set, and privateKey is null + cert = certRsc.getKeyInfo(); + assertEquals(certificate2, cert.getCertificate(), "cert properly set"); + assertNull(cert.getPrivateKey(), "privateKey nullified"); + + // Upload certificate with header - should be stored without header + form = new MultipartFormDataOutput(); + form.addFormData("keystoreFormat", "Certificate PEM", MediaType.TEXT_PLAIN_TYPE); + + String certificate2WithHeaders = PemUtils.BEGIN_CERT + "\n" + certificate2 + "\n" + PemUtils.END_CERT; + + form.addFormData("file", certificate2WithHeaders.getBytes(StandardCharsets.US_ASCII), MediaType.APPLICATION_OCTET_STREAM_TYPE); + cert = certRsc.uploadJks(form); + assertNotNull(cert, "cert not null"); + assertEquals(certificate2, cert.getCertificate(),"cert properly extracted"); + assertNull(cert.getPrivateKey(), "privateKey not included"); + + // Get the certificate again - to make sure cert is set, and privateKey is null + cert = certRsc.getKeyInfo(); + assertEquals(certificate2, cert.getCertificate(), "cert properly set"); + assertNull(cert.getPrivateKey(), "privateKey nullified"); + } + + @Test + public void testDownloadKeystore() throws Exception { + ClientAttributeCertificateResource certRsc = managedClient.admin().getCertficateResource("jwt.credential"); + + // generate a key pair first + CertificateRepresentation certrep = certRsc.generate(); + + KeystoreUtil.KeystoreFormat preferredKeystoreType = KeystoreUtil.KeystoreFormat.valueOf(adminClient.serverInfo().getInfo().getCryptoInfo().getSupportedKeystoreTypes().get(0)); + + // download the key and certificate + KeyStoreConfig config = new KeyStoreConfig(); + config.setFormat(preferredKeystoreType.toString()); + config.setKeyAlias("alias"); + config.setKeyPassword("keyPass"); + config.setStorePassword("storePass"); + byte[] result = certRsc.getKeystore(config); + + KeyStore keyStore = CryptoIntegration.getProvider().getKeyStore(preferredKeystoreType); + keyStore.load(new ByteArrayInputStream(result), "storePass".toCharArray()); + Key key = keyStore.getKey("alias", "keyPass".toCharArray()); + Certificate cert = keyStore.getCertificate("alias"); + + assertInstanceOf(X509Certificate.class, cert, "Certificat is X509"); + String keyPem = KeycloakModelUtils.getPemFromKey(key); + String certPem = KeycloakModelUtils.getPemFromCertificate((X509Certificate) cert); + + assertEquals(certrep.getPrivateKey(), keyPem, "key match"); + assertEquals(certrep.getCertificate(), certPem, "cert match"); + } + + @Test + public void testGenerateAndDownloadKeystore() throws Exception { + ClientAttributeCertificateResource certRsc = managedClient.admin().getCertficateResource("jwt.credential"); + + // generate a key pair first + CertificateRepresentation firstcert = certRsc.generate(); + + KeystoreUtil.KeystoreFormat preferredKeystoreType = KeystoreUtil.KeystoreFormat.valueOf(adminClient.serverInfo().getInfo().getCryptoInfo().getSupportedKeystoreTypes().get(0)); + + KeyStoreConfig config = new KeyStoreConfig(); + config.setFormat(preferredKeystoreType.toString()); + config.setKeyAlias("alias"); + config.setKeyPassword("keyPass"); + config.setStorePassword("storePass"); + config.setKeySize(4096); + config.setValidity(3); + byte[] result = certRsc.generateAndGetKeystore(config); + KeyStore keyStore = CryptoIntegration.getProvider().getKeyStore(preferredKeystoreType); + keyStore.load(new ByteArrayInputStream(result), "storePass".toCharArray()); + Key key = keyStore.getKey("alias", "keyPass".toCharArray()); + Certificate cert = keyStore.getCertificate("alias"); + + assertInstanceOf(X509Certificate.class, cert, "Certificat is X509"); + String keyPem = KeycloakModelUtils.getPemFromKey(key); + String certPem = KeycloakModelUtils.getPemFromCertificate((X509Certificate) cert); + + assertNotEquals(firstcert.getPrivateKey(), keyPem, "new key generated"); + assertNotEquals(firstcert.getCertificate(), certPem, "new cert generated"); + } +} diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/realm/RealmDefaultConfigTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/realm/RealmDefaultConfigTest.java index 138dfa86c25..1e28d759db2 100644 --- a/tests/base/src/test/java/org/keycloak/tests/admin/realm/RealmDefaultConfigTest.java +++ b/tests/base/src/test/java/org/keycloak/tests/admin/realm/RealmDefaultConfigTest.java @@ -19,7 +19,6 @@ package org.keycloak.tests.admin.realm; import jakarta.ws.rs.NotFoundException; import org.apache.commons.io.IOUtils; -import org.bouncycastle.util.Strings; import org.junit.jupiter.api.Test; import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.events.admin.OperationType; @@ -126,9 +125,9 @@ public class RealmDefaultConfigTest extends AbstractRealmTest { role = managedRealm.admin().roles().get("test").toRepresentation(); assertNotNull(role); - managedRealm.admin().roles().get(Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + Strings.toLowerCase(managedRealm.getName())).addComposites(Collections.singletonList(role)); + managedRealm.admin().roles().get(Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + managedRealm.getName().toLowerCase()).addComposites(Collections.singletonList(role)); - AdminEventAssertion.assertEvent(adminEvents.poll(), OperationType.CREATE, AdminEventPaths.roleResourceCompositesPath(Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + Strings.toLowerCase(managedRealm.getName())), Collections.singletonList(role), ResourceType.REALM_ROLE); + AdminEventAssertion.assertEvent(adminEvents.poll(), OperationType.CREATE, AdminEventPaths.roleResourceCompositesPath(Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + managedRealm.getName().toLowerCase()), Collections.singletonList(role), ResourceType.REALM_ROLE); managedRealm.admin().roles().deleteRole("test"); AdminEventAssertion.assertEvent(adminEvents.poll(), OperationType.DELETE, AdminEventPaths.roleResourcePath("test"), ResourceType.REALM_ROLE); diff --git a/tests/base/src/test/java/org/keycloak/tests/suites/FipsNonStrictTestSuite.java b/tests/base/src/test/java/org/keycloak/tests/suites/FipsNonStrictTestSuite.java new file mode 100644 index 00000000000..969ad24b3c0 --- /dev/null +++ b/tests/base/src/test/java/org/keycloak/tests/suites/FipsNonStrictTestSuite.java @@ -0,0 +1,53 @@ +package org.keycloak.tests.suites; + +import org.junit.platform.suite.api.AfterSuite; +import org.junit.platform.suite.api.BeforeSuite; +import org.junit.platform.suite.api.SelectClasses; +import org.junit.platform.suite.api.Suite; +import org.keycloak.common.Profile; +import org.keycloak.common.util.KeystoreUtil; +import org.keycloak.testframework.https.CertificatesConfig; +import org.keycloak.testframework.https.CertificatesConfigBuilder; +import org.keycloak.testframework.injection.SuiteSupport; +import org.keycloak.testframework.server.KeycloakServerConfig; +import org.keycloak.testframework.server.KeycloakServerConfigBuilder; +import org.keycloak.tests.admin.ServerInfoTest; +import org.keycloak.tests.admin.client.CredentialsTest; + +@Suite +@SelectClasses({CredentialsTest.class, ServerInfoTest.class}) +public class FipsNonStrictTestSuite { + + @BeforeSuite + public static void beforeSuite() { + SuiteSupport.startSuite() + .registerServerConfig(FipsNonStrictServerConfig.class) + .registerSupplierConfig("certificates", FipsNonStrictCertificatesConfig.class);; + } + + @AfterSuite + public static void afterSuite() { + SuiteSupport.stopSuite(); + } + + public static class FipsNonStrictServerConfig implements KeycloakServerConfig { + + @Override + public KeycloakServerConfigBuilder configure(KeycloakServerConfigBuilder config) { + return config.features(Profile.Feature.FIPS).tlsEnabled(true) + .option("fips-mode", "non-strict") + .dependency("org.bouncycastle", "bc-fips") + .dependency("org.bouncycastle", "bctls-fips") + .dependency("org.bouncycastle", "bcpkix-fips") + .dependency("org.bouncycastle", "bcutil-fips"); + } + } + + public static class FipsNonStrictCertificatesConfig implements CertificatesConfig { + + @Override + public CertificatesConfigBuilder configure(CertificatesConfigBuilder config) { + return config.keystoreFormat(KeystoreUtil.KeystoreFormat.PKCS12); + } + } +} diff --git a/tests/base/src/test/java/org/keycloak/tests/suites/FipsStrictTestSuite.java b/tests/base/src/test/java/org/keycloak/tests/suites/FipsStrictTestSuite.java new file mode 100644 index 00000000000..c574a8b7851 --- /dev/null +++ b/tests/base/src/test/java/org/keycloak/tests/suites/FipsStrictTestSuite.java @@ -0,0 +1,56 @@ +package org.keycloak.tests.suites; + +import org.junit.platform.suite.api.AfterSuite; +import org.junit.platform.suite.api.BeforeSuite; +import org.junit.platform.suite.api.SelectClasses; +import org.junit.platform.suite.api.Suite; +import org.keycloak.common.Profile; +import org.keycloak.common.util.KeystoreUtil; +import org.keycloak.testframework.https.CertificatesConfig; +import org.keycloak.testframework.https.CertificatesConfigBuilder; +import org.keycloak.testframework.injection.SuiteSupport; +import org.keycloak.testframework.server.KeycloakServerConfig; +import org.keycloak.testframework.server.KeycloakServerConfigBuilder; +import org.keycloak.tests.admin.ServerInfoTest; +import org.keycloak.tests.admin.client.CredentialsTest; + +@Suite +@SelectClasses({CredentialsTest.class, ServerInfoTest.class}) +public class FipsStrictTestSuite { + + @BeforeSuite + public static void beforeSuite() { + SuiteSupport.startSuite() + .registerServerConfig(FipsStrictServerConfig.class) + .registerSupplierConfig("certificates", FipsStrictCertificatesConfig.class); + } + + @AfterSuite + public static void afterSuite() { + SuiteSupport.stopSuite(); + } + + public static class FipsStrictServerConfig implements KeycloakServerConfig { + + @Override + public KeycloakServerConfigBuilder configure(KeycloakServerConfigBuilder config) { + return config.features(Profile.Feature.FIPS).tlsEnabled(true) + .option("fips-mode", "strict") + .option("spi-password-hashing-pbkdf2-max-padding-length", "14") + .option("spi-password-hashing-pbkdf2-sha256-max-padding-length", "14") + .option("spi-password-hashing-pbkdf2-sha512-max-padding-length", "14") + .dependency("org.bouncycastle", "bc-fips") + .dependency("org.bouncycastle", "bctls-fips") + .dependency("org.bouncycastle", "bcpkix-fips") + .dependency("org.bouncycastle", "bcutil-fips"); + } + } + + public static class FipsStrictCertificatesConfig implements CertificatesConfig { + + @Override + public CertificatesConfigBuilder configure(CertificatesConfigBuilder config) { + return config.keystoreFormat(KeystoreUtil.KeystoreFormat.BCFKS); + } + } +} diff --git a/tests/base/src/test/java/org/keycloak/tests/suites/JDKTestSuite.java b/tests/base/src/test/java/org/keycloak/tests/suites/JDKTestSuite.java index bb952522eb2..ba5f54c5410 100644 --- a/tests/base/src/test/java/org/keycloak/tests/suites/JDKTestSuite.java +++ b/tests/base/src/test/java/org/keycloak/tests/suites/JDKTestSuite.java @@ -2,10 +2,9 @@ package org.keycloak.tests.suites; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; -import org.keycloak.tests.admin.AdminHeadersTest; +import org.keycloak.tests.admin.client.CredentialsTest; @Suite -// TODO: Select relevant test classes or packages once they have been migrated -@SelectClasses(AdminHeadersTest.class) +@SelectClasses({CredentialsTest.class}) public class JDKTestSuite { } diff --git a/tests/utils/src/main/java/org/keycloak/tests/utils/FipsUtils.java b/tests/utils/src/main/java/org/keycloak/tests/utils/FipsUtils.java new file mode 100644 index 00000000000..3053d58413a --- /dev/null +++ b/tests/utils/src/main/java/org/keycloak/tests/utils/FipsUtils.java @@ -0,0 +1,32 @@ +package org.keycloak.tests.utils; + +import org.keycloak.representations.info.ServerInfoRepresentation; + +public class FipsUtils { + + private final String cryptoProvider; + + private FipsUtils(ServerInfoRepresentation info) { + this.cryptoProvider = info.getCryptoInfo().getCryptoProvider(); + } + + public static FipsUtils create(ServerInfoRepresentation info) { + return new FipsUtils(info); + } + + public String[] getExpectedSupportedKeyStoreTypes() { + return switch (cryptoProvider) { + case "FIPS1402Provider" -> new String[] { "PKCS12", "BCFKS" }; + case "Fips1402StrictCryptoProvider" -> new String[] { "BCFKS" }; + default -> new String[] { "JKS", "PKCS12", "BCFKS" }; + }; + } + + public String[] getExpectedSupportedRsaKeySizes() { + return switch (cryptoProvider) { + case "Fips1402StrictCryptoProvider" -> new String[]{"2048", "3072", "4096"}; + default -> new String[]{"1024", "2048", "3072", "4096"}; + }; + } + +} diff --git a/tests/utils/src/main/java/org/keycloak/tests/utils/admin/GenerateKeystoreForTestUtil.java b/tests/utils/src/main/java/org/keycloak/tests/utils/admin/GenerateKeystoreForTestUtil.java new file mode 100644 index 00000000000..9b9e3c1ea53 --- /dev/null +++ b/tests/utils/src/main/java/org/keycloak/tests/utils/admin/GenerateKeystoreForTestUtil.java @@ -0,0 +1,67 @@ +package org.keycloak.tests.utils.admin; + +import org.keycloak.common.crypto.CryptoIntegration; +import org.keycloak.common.util.CertificateUtils; +import org.keycloak.common.util.KeyUtils; +import org.keycloak.common.util.PemUtils; +import org.keycloak.representations.idm.CertificateRepresentation; + +import java.io.File; +import java.io.FileOutputStream; +import java.nio.file.Path; +import java.security.KeyPair; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; + +public class GenerateKeystoreForTestUtil { + + private final static Path KEYSTORES_DIR = Path.of(System.getProperty("java.io.tmpdir")); + + public static KeystoreInfo generateKeystore(org.keycloak.common.util.KeystoreUtil.KeystoreFormat keystoreType, String subject, String keystorePassword, String keyPassword) throws Exception { + return generateKeystore(keystoreType, subject, keystorePassword, keyPassword, KeyUtils.generateRsaKeyPair(2048)); + } + + public static KeystoreInfo generateKeystore(org.keycloak.common.util.KeystoreUtil.KeystoreFormat keystoreType, String subject, String keystorePassword, String keyPassword, KeyPair keyPair) throws Exception { + X509Certificate certificate = CertificateUtils.generateV1SelfSignedCertificate(keyPair, subject); + return generateKeystore(keystoreType, subject, keystorePassword, keyPassword, keyPair.getPrivate(), certificate); + } + + public static KeystoreInfo generateKeystore(org.keycloak.common.util.KeystoreUtil.KeystoreFormat keystoreType, + String subject, String keystorePassword, String keyPassword, PrivateKey privKey, Certificate certificate) throws Exception { + String fileName = "keystore." + keystoreType.getPrimaryExtension(); + + KeyStore keyStore = CryptoIntegration.getProvider().getKeyStore(keystoreType); + keyStore.load(null, null); + Certificate[] chain = {certificate}; + keyStore.setKeyEntry(subject, privKey, keyPassword.trim().toCharArray(), chain); + + File file = KEYSTORES_DIR.resolve(fileName).toFile(); + keyStore.store(new FileOutputStream(file), keystorePassword.trim().toCharArray()); + + CertificateRepresentation certRep = new CertificateRepresentation(); + certRep.setPrivateKey(PemUtils.encodeKey(privKey)); + certRep.setPublicKey(PemUtils.encodeKey(certificate.getPublicKey())); + certRep.setCertificate(PemUtils.encodeCertificate(certificate)); + return new KeystoreInfo(certRep, file); + } + + public static class KeystoreInfo { + private final CertificateRepresentation certificateInfo; + private final File keystoreFile; + + private KeystoreInfo(CertificateRepresentation certificateInfo, File keystoreFile) { + this.certificateInfo = certificateInfo; + this.keystoreFile = keystoreFile; + } + + public CertificateRepresentation getCertificateInfo() { + return certificateInfo; + } + + public File getKeystoreFile() { + return keystoreFile; + } + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/CredentialsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/CredentialsTest.java deleted file mode 100644 index 221305b6085..00000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/CredentialsTest.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors - * as indicated by the @author tags. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.keycloak.testsuite.admin.client; - -import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput; -import org.junit.Before; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.keycloak.admin.client.resource.ClientAttributeCertificateResource; -import org.keycloak.admin.client.resource.ClientResource; -import org.keycloak.common.crypto.CryptoIntegration; -import org.keycloak.common.util.KeystoreUtil; -import org.keycloak.common.util.PemUtils; -import org.keycloak.events.admin.OperationType; -import org.keycloak.events.admin.ResourceType; -import org.keycloak.models.utils.KeycloakModelUtils; -import org.keycloak.representations.KeyStoreConfig; -import org.keycloak.representations.idm.CertificateRepresentation; -import org.keycloak.representations.idm.ClientRepresentation; -import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.testsuite.AbstractClientTest; -import org.keycloak.testsuite.util.AdminEventPaths; -import org.keycloak.testsuite.util.KeystoreUtils; - -import jakarta.ws.rs.core.MediaType; -import java.io.ByteArrayInputStream; -import java.io.FileInputStream; -import java.nio.charset.Charset; -import java.security.Key; -import java.security.KeyStore; -import java.security.cert.Certificate; -import java.security.cert.X509Certificate; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * - * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. - */ -public class CredentialsTest extends AbstractClientTest { - - private ClientResource accountClient; - private String accountClientDbId; - - @Before - public void init() { - accountClient = findClientResourceById("account"); - accountClientDbId = accountClient.toRepresentation().getId(); - } - - @Test - public void testGetAndRegenerateSecret() { - CredentialRepresentation oldCredential = accountClient.getSecret(); - CredentialRepresentation newCredential = accountClient.generateNewSecret(); - - CredentialRepresentation secretRep = new CredentialRepresentation(); - secretRep.setType(CredentialRepresentation.SECRET); - assertAdminEvents.assertEvent(getRealmId(), OperationType.ACTION, AdminEventPaths.clientGenerateSecretPath(accountClientDbId), secretRep, ResourceType.CLIENT); - - assertNotNull(oldCredential); - assertNotNull(newCredential); - assertNotEquals(newCredential.getValue(), oldCredential.getValue()); - assertEquals(newCredential.getValue(), accountClient.getSecret().getValue()); - } - - @Test - public void testGetAndRegenerateRegistrationAccessToken() { - ClientRepresentation rep = accountClient.toRepresentation(); - String oldToken = rep.getRegistrationAccessToken(); - String newToken = accountClient.regenerateRegistrationAccessToken().getRegistrationAccessToken(); - assertNull(oldToken); // registration access token not saved in ClientRep - assertNotNull(newToken); // it's only available via regenerateRegistrationAccessToken() - assertNull(accountClient.toRepresentation().getRegistrationAccessToken()); - - // Test event - ClientRepresentation testedRep = new ClientRepresentation(); - testedRep.setClientId(rep.getClientId()); - testedRep.setRegistrationAccessToken(newToken); - assertAdminEvents.assertEvent(getRealmId(), OperationType.ACTION, AdminEventPaths.clientRegenerateRegistrationAccessTokenPath(accountClientDbId), testedRep, ResourceType.CLIENT); - } - - @Test - public void testGetCertificateResource() { - ClientAttributeCertificateResource certRsc = accountClient.getCertficateResource("jwt.credential"); - CertificateRepresentation cert = certRsc.generate(); - CertificateRepresentation certFromGet = certRsc.getKeyInfo(); - assertEquals(cert.getCertificate(), certFromGet.getCertificate()); - assertEquals(cert.getPrivateKey(), certFromGet.getPrivateKey()); - - assertAdminEvents.assertEvent(getRealmId(), OperationType.ACTION, AdminEventPaths.clientCertificateGenerateSecretPath(accountClientDbId, "jwt.credential"), cert, ResourceType.CLIENT); - } - - @Test - public void testUploadKeyAndCertificate() throws Exception { - TemporaryFolder folder = new TemporaryFolder(); - folder.create(); - try { - String certificate2 = "MIICnTCCAYUCBgFPPQDGxTANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdjbGllbnQxMB4XDTE1MDgxNzE4NTAwNVoXDTI1MDgxNzE4NTE0NVowEjEQMA4GA1UEAwwHY2xpZW50MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMMw3PaBffWxgS2PYSDDBp6As+cNvv9kt2C4f/RDAGmvSIHPFev9kuQiKs3Oaws3ZsV4JG3qHEuYgnh9W4vfe3DwNwtD1bjL5FYBhPBFTw0lAQECYxaBHnkjHwUKp957FqdSPPICm3LjmTcEdlH+9dpp9xHCMbbiNiWDzWI1xSxC8Fs2d0hwz1sd+Q4QeTBPIBWcPM+ICZtNG5MN+ORfayu4X+Me5d0tXG2fQO//rAevk1i5IFjKZuOjTwyKB5SJIY4b8QTeg0g/50IU7Ht00Pxw6CK02dHS+FvXHasZlD3ckomqCDjStTBWdhJo5dST0CbOqalkkpLlCCbGA1yEQRsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAUIMeJ+EAo8eNpCG/nXImacjrKakbFnZYBGD/gqeTGaZynkX+jgBSructTHR83zSH+yELEhsAy+3BfK4EEihp+PEcRnK2fASVkHste8AQ7rlzC+HGGirlwrVhWCdizNUCGK80DE537IZ7nmZw6LFG9P5/Q2MvCsOCYjRUvMkukq6TdXBXR9tETwZ+0gpSfsOxjj0ZF7ftTRUSzx4rFfcbM9fRNdVizdOuKGc8HJPA5lLOxV6CyaYIvi3y5RlQI1OHeS34lE4w9CNPRFa/vdxXvN7ClyzA0HMFNWxBN7pC/Ht/FbhSvaAagJBHg+vCrcY5C26Oli7lAglf/zZrwUPs0w=="; - - ClientAttributeCertificateResource certRsc = accountClient.getCertficateResource("jwt.credential"); - - KeystoreUtil.KeystoreFormat preferredKeystoreType = KeystoreUtils.getPreferredKeystoreType(); - - // Generate keystore file and upload privateKey and certificate from it as JKS store (or eventually PKCS12 or BCFKS store according to which one is preferred type) - KeystoreUtils.KeystoreInfo generatedKeystore = KeystoreUtils.generateKeystore(folder, preferredKeystoreType, "clientkey", "storepass", "keypass"); - MultipartFormDataOutput keyCertForm = new MultipartFormDataOutput(); - - keyCertForm.addFormData("keystoreFormat", preferredKeystoreType.toString(), MediaType.TEXT_PLAIN_TYPE); - keyCertForm.addFormData("keyAlias", "clientkey", MediaType.TEXT_PLAIN_TYPE); - keyCertForm.addFormData("keyPassword", "keypass", MediaType.TEXT_PLAIN_TYPE); - keyCertForm.addFormData("storePassword", "storepass", MediaType.TEXT_PLAIN_TYPE); - - FileInputStream fs = new FileInputStream(generatedKeystore.getKeystoreFile()); - byte [] content = fs.readAllBytes(); - fs.close(); - keyCertForm.addFormData("file", content, MediaType.APPLICATION_OCTET_STREAM_TYPE); - CertificateRepresentation cert = certRsc.uploadJks(keyCertForm); - - // Returned cert is not the new state but rather what was extracted from inputs - assertNotNull("cert not null", cert); - assertEquals("cert properly extracted", generatedKeystore.getCertificateInfo().getCertificate(), cert.getCertificate()); - assertEquals("privateKey properly extracted", generatedKeystore.getCertificateInfo().getPrivateKey(), cert.getPrivateKey()); - - // Get the certificate - to make sure cert was properly updated - cert = certRsc.getKeyInfo(); - assertEquals("cert properly set", generatedKeystore.getCertificateInfo().getCertificate(), cert.getCertificate()); - assertEquals("privateKey properly set", generatedKeystore.getCertificateInfo().getPrivateKey(), cert.getPrivateKey()); - - // Upload a different certificate via /upload-certificate, privateKey should be nullified - MultipartFormDataOutput form = new MultipartFormDataOutput(); - form.addFormData("keystoreFormat", "Certificate PEM", MediaType.TEXT_PLAIN_TYPE); - form.addFormData("file", certificate2.getBytes(Charset.forName("ASCII")), MediaType.APPLICATION_OCTET_STREAM_TYPE); - cert = certRsc.uploadJksCertificate(form); - assertNotNull("cert not null", cert); - assertEquals("cert properly extracted", certificate2, cert.getCertificate()); - assertNull("privateKey not included", cert.getPrivateKey()); - - // Get the certificate - to make sure cert was properly updated, and privateKey is null - cert = certRsc.getKeyInfo(); - assertEquals("cert properly set", certificate2, cert.getCertificate()); - assertNull("privateKey nullified", cert.getPrivateKey()); - - // Re-upload the private key - certRsc.uploadJks(keyCertForm); - - // Upload certificate as PEM via /upload - nullifies the private key - form = new MultipartFormDataOutput(); - form.addFormData("keystoreFormat", "Certificate PEM", MediaType.TEXT_PLAIN_TYPE); - form.addFormData("file", certificate2.getBytes(Charset.forName("ASCII")), MediaType.APPLICATION_OCTET_STREAM_TYPE); - cert = certRsc.uploadJks(form); - assertNotNull("cert not null", cert); - assertEquals("cert properly extracted", certificate2, cert.getCertificate()); - assertNull("privateKey not included", cert.getPrivateKey()); - - // Get the certificate again - to make sure cert is set, and privateKey is null - cert = certRsc.getKeyInfo(); - assertEquals("cert properly set", certificate2, cert.getCertificate()); - assertNull("privateKey nullified", cert.getPrivateKey()); - - // Upload certificate with header - should be stored without header - form = new MultipartFormDataOutput(); - form.addFormData("keystoreFormat", "Certificate PEM", MediaType.TEXT_PLAIN_TYPE); - - String certificate2WithHeaders = PemUtils.BEGIN_CERT + "\n" + certificate2 + "\n" + PemUtils.END_CERT; - - form.addFormData("file", certificate2WithHeaders.getBytes(Charset.forName("ASCII")), MediaType.APPLICATION_OCTET_STREAM_TYPE); - cert = certRsc.uploadJks(form); - assertNotNull("cert not null", cert); - assertEquals("cert properly extracted", certificate2, cert.getCertificate()); - assertNull("privateKey not included", cert.getPrivateKey()); - - // Get the certificate again - to make sure cert is set, and privateKey is null - cert = certRsc.getKeyInfo(); - assertEquals("cert properly set", certificate2, cert.getCertificate()); - assertNull("privateKey nullified", cert.getPrivateKey()); - } finally { - folder.delete(); - } - } - - @Test - public void testDownloadKeystore() throws Exception { - ClientAttributeCertificateResource certRsc = accountClient.getCertficateResource("jwt.credential"); - - // generate a key pair first - CertificateRepresentation certrep = certRsc.generate(); - - KeystoreUtil.KeystoreFormat preferredKeystoreType = KeystoreUtils.getPreferredKeystoreType(); - - // download the key and certificate - KeyStoreConfig config = new KeyStoreConfig(); - config.setFormat(preferredKeystoreType.toString()); - config.setKeyAlias("alias"); - config.setKeyPassword("keyPass"); - config.setStorePassword("storePass"); - byte[] result = certRsc.getKeystore(config); - - KeyStore keyStore = CryptoIntegration.getProvider().getKeyStore(preferredKeystoreType); - keyStore.load(new ByteArrayInputStream(result), "storePass".toCharArray()); - Key key = keyStore.getKey("alias", "keyPass".toCharArray()); - Certificate cert = keyStore.getCertificate("alias"); - - assertTrue("Certificat is X509", cert instanceof X509Certificate); - String keyPem = KeycloakModelUtils.getPemFromKey(key); - String certPem = KeycloakModelUtils.getPemFromCertificate((X509Certificate) cert); - - assertEquals("key match", certrep.getPrivateKey(), keyPem); - assertEquals("cert match", certrep.getCertificate(), certPem); - } - - @Test - public void testGenerateAndDownloadKeystore() throws Exception { - ClientAttributeCertificateResource certRsc = accountClient.getCertficateResource("jwt.credential"); - - // generate a key pair first - CertificateRepresentation firstcert = certRsc.generate(); - - KeystoreUtil.KeystoreFormat preferredKeystoreType = KeystoreUtils.getPreferredKeystoreType(); - - KeyStoreConfig config = new KeyStoreConfig(); - config.setFormat(preferredKeystoreType.toString()); - config.setKeyAlias("alias"); - config.setKeyPassword("keyPass"); - config.setStorePassword("storePass"); - config.setKeySize(4096); - config.setValidity(3); - byte[] result = certRsc.generateAndGetKeystore(config); - KeyStore keyStore = CryptoIntegration.getProvider().getKeyStore(preferredKeystoreType); - keyStore.load(new ByteArrayInputStream(result), "storePass".toCharArray()); - Key key = keyStore.getKey("alias", "keyPass".toCharArray()); - Certificate cert = keyStore.getCertificate("alias"); - - assertTrue("Certificat is X509", cert instanceof X509Certificate); - String keyPem = KeycloakModelUtils.getPemFromKey(key); - String certPem = KeycloakModelUtils.getPemFromCertificate((X509Certificate) cert); - - assertNotEquals("new key generated", firstcert.getPrivateKey(), keyPem); - assertNotEquals("new cert generated", firstcert.getCertificate(), certPem); - } -} diff --git a/testsuite/integration-arquillian/tests/base/testsuites/fips-suite b/testsuite/integration-arquillian/tests/base/testsuites/fips-suite index f599d910e05..14a2acacdca 100644 --- a/testsuite/integration-arquillian/tests/base/testsuites/fips-suite +++ b/testsuite/integration-arquillian/tests/base/testsuites/fips-suite @@ -3,9 +3,7 @@ LoginTotpTest PasswordHashingTest ClientAuthSignedJWTTest ClientAuthEdDSASignedJWTTest -CredentialsTest JavaKeystoreKeyProviderTest -ServerInfoTest UserFederationLdapConnectionTest LDAPUserLoginTest org.keycloak.testsuite.x509.** diff --git a/testsuite/integration-arquillian/tests/base/testsuites/jdk-suite b/testsuite/integration-arquillian/tests/base/testsuites/jdk-suite index 9b7150e99b1..b578cbca934 100644 --- a/testsuite/integration-arquillian/tests/base/testsuites/jdk-suite +++ b/testsuite/integration-arquillian/tests/base/testsuites/jdk-suite @@ -1,6 +1,5 @@ AccountRestServiceTest AuthorizationCodeTest -CredentialsTest DeployedScriptAuthenticatorTest ExportImportTest GeneratedRsaKeyProviderTest