From 36bd76957de8f85d45b5232bf3e81952d5e10279 Mon Sep 17 00:00:00 2001 From: mposolda Date: Thu, 8 Dec 2022 18:54:14 +0100 Subject: [PATCH] Make Keycloak FIPS working with OpenJDK 17 on FIPS enabled RHEL Closes #15721 --- crypto/fips1402/pom.xml | 15 ------ .../crypto/fips/FIPS1402Provider.java | 39 +++++++++++--- .../src/test/resources/kc.java.security | 51 ------------------ docs/fips.md | 3 +- .../client/admin/cli/util/AuthUtil.java | 3 +- .../registration/cli/util/AuthUtil.java | 4 +- .../mappers/ClassLoaderPropertyMappers.java | 2 +- .../auth-server/common/fips/kc.java.security | 17 +++--- .../servers/auth-server/quarkus/pom.xml | 2 +- .../testsuite/cli/admin/KcAdmTest.java | 25 ++++++--- .../testsuite/cli/registration/KcRegTest.java | 25 ++++++--- .../cli/kcadm/admin-cli-keystore.p12 | Bin 0 -> 2526 bytes .../resources/cli/kcreg/reg-cli-keystore.p12 | Bin 0 -> 2522 bytes 13 files changed, 87 insertions(+), 99 deletions(-) delete mode 100644 crypto/fips1402/src/test/resources/kc.java.security create mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/cli/kcadm/admin-cli-keystore.p12 create mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/cli/kcreg/reg-cli-keystore.p12 diff --git a/crypto/fips1402/pom.xml b/crypto/fips1402/pom.xml index 1ce9a822ef..cd5f1cd0b7 100644 --- a/crypto/fips1402/pom.xml +++ b/crypto/fips1402/pom.xml @@ -89,19 +89,4 @@ - - - - - maven-surefire-plugin - - - ${basedir}/target/test-classes/kc.java.security - - - - - - - \ No newline at end of file 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 3e6b92d1d2..cb0582ecd3 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 @@ -9,6 +9,7 @@ import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Provider; +import java.security.SecureRandom; import java.security.spec.ECField; import java.security.spec.ECFieldF2m; import java.security.spec.ECFieldFp; @@ -83,7 +84,7 @@ public class FIPS1402Provider implements CryptoProvider { Security.insertProviderAt(new KeycloakFipsSecurityProvider(bcFipsProvider), 1); if (existingBcFipsProvider == null) { - Security.insertProviderAt(this.bcFipsProvider, 2); + checkSecureRandom(() -> Security.insertProviderAt(this.bcFipsProvider, 2)); Provider bcJsseProvider = new BouncyCastleJsseProvider("fips:BCFIPS"); Security.insertProviderAt(bcJsseProvider, 3); log.debugf("Inserted security providers: %s", Arrays.asList(this.bcFipsProvider.getName(),bcJsseProvider.getName())); @@ -191,11 +192,7 @@ public class FIPS1402Provider implements CryptoProvider { @Override public KeyStore getKeyStore(KeystoreFormat format) throws KeyStoreException, NoSuchProviderException { - if (format == KeystoreFormat.JKS) { - return KeyStore.getInstance(format.toString()); - } else { - return KeyStore.getInstance(format.toString(), BouncyIntegration.PROVIDER); - } + return KeyStore.getInstance(format.toString(), BouncyIntegration.PROVIDER); } @Override @@ -262,4 +259,34 @@ public class FIPS1402Provider implements CryptoProvider { }; } + + // BCFIPS require "SecureRandom.getInstanceStrong" to be available. But it may not be available on RHEL 8 on OpenJDK 17 due the https://bugzilla.redhat.com/show_bug.cgi?id=2155060 + private void checkSecureRandom(Runnable insertBcFipsProvider) { + try { + SecureRandom sr = SecureRandom.getInstanceStrong(); + log.debugf("Strong secure random available. Algorithm: %s, Provider: %s", sr.getAlgorithm(), sr.getProvider()); + insertBcFipsProvider.run(); + } catch (NoSuchAlgorithmException nsae) { + + // Fallback to regular SecureRandom + SecureRandom secRandom = new SecureRandom(); + String origStrongAlgs = Security.getProperty("securerandom.strongAlgorithms"); + String usedAlg = secRandom.getAlgorithm() + ":" + secRandom.getProvider().getName(); + log.debugf("Strong secure random not available. Tried algorithms: %s. Using algorithm as a fallback for strong secure random: %s", origStrongAlgs, usedAlg); + + String strongAlgs = origStrongAlgs == null ? usedAlg : usedAlg + "," + origStrongAlgs; + Security.setProperty("securerandom.strongAlgorithms", strongAlgs); + + try { + // Need to insert BCFIPS provider to security providers with "strong algorithm" available + insertBcFipsProvider.run(); + SecureRandom.getInstance("DEFAULT", "BCFIPS"); + log.debugf("Initialized BCFIPS secured random"); + } catch (NoSuchAlgorithmException | NoSuchProviderException nsaee) { + throw new IllegalStateException("Not possible to initiate BCFIPS secure random", nsaee); + } finally { + Security.setProperty("securerandom.strongAlgorithms", origStrongAlgs != null ? origStrongAlgs : ""); + } + } + } } diff --git a/crypto/fips1402/src/test/resources/kc.java.security b/crypto/fips1402/src/test/resources/kc.java.security deleted file mode 100644 index 9267176d29..0000000000 --- a/crypto/fips1402/src/test/resources/kc.java.security +++ /dev/null @@ -1,51 +0,0 @@ -# Configuration file just with the security properties, which are supposed to be overriden. The properties, which are not mentioned in this file, -# are inherited from the default java.security file bundled within the Java distribution. -# -# NOTE: Each property is specified 2 times. This is so the same file can be used on both FIPS based RHEL host (which uses "fips" prefixed properties by default) -# and the non-fips based (EG. when running the tests on GH actions) - -# -# List of providers and their preference orders (see above). Used on the host without FIPS (EG. when running the tests on GH actions) -# Uses only BouncyCastle FIPS providers to make sure to use only FIPS compliant cryptography. -# -security.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -security.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider fips:BCFIPS -security.provider.3= - -# -# Security providers used when global crypto-policies are set to FIPS (Usually it is used when FIPS enabled on system/JVM level) -# -fips.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -fips.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider fips:BCFIPS -fips.provider.3= - -# Commented this provider for now (and also other providers) as it uses lots of non-FIPS services. -# See https://access.redhat.com/documentation/en-us/openjdk/11/html-single/configuring_openjdk_11_on_rhel_with_fips/index#ref_openjdk-default-fips-configuration_openjdk -# fips.provider.2=SUN - -# -# Default keystore type. -# -keystore.type=PKCS12 -fips.keystore.type=PKCS12 - -# This is needed especially if we cannot add security provider "com.sun.net.ssl.internal.ssl.Provider BCFIPS" as a security provider. -# OpenJDK has "SunX509" as default algorithm, but that one is not supported by BCJSSE. So adding the Sun provider delegating to BCFIPS is needed (as above) -# or changing default algorithm as described here -ssl.KeyManagerFactory.algorithm=PKIX -fips.ssl.KeyManagerFactory.algorithm=PKIX - -ssl.TrustManagerFactory.algorithm=PKIX -fips.ssl.TrustManagerFactory.algorithm=PKIX - -# -# Controls compatibility mode for JKS and PKCS12 keystore types. -# -# When set to 'true', both JKS and PKCS12 keystore types support loading -# keystore files in either JKS or PKCS12 format. When set to 'false' the -# JKS keystore type supports loading only JKS keystore files and the PKCS12 -# keystore type supports loading only PKCS12 keystore files. -# -# This is set to false as BCFIPS providers don't support JKS -keystore.type.compat=false -fips.keystore.type.compat=false diff --git a/docs/fips.md b/docs/fips.md index e41c09d1d7..6de167b765 100644 --- a/docs/fips.md +++ b/docs/fips.md @@ -66,8 +66,7 @@ For the `fips-mode`, he alternative is to use `--fips-mode=strict` in which case which means even stricter security algorithms. As mentioned above, strict mode won't work with `pkcs12` keystore: ``` -./kc.sh build --fips-mode=enabled -./kc.sh start --optimized --hostname=localhost \ +./kc.sh start --fips-mode=enabled --hostname=localhost \ --https-key-store-file=$PWD/$KEYSTORE_FILE \ --https-key-store-type=$KEYSTORE_FORMAT \ --https-key-store-password=passwordpassword \ diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/AuthUtil.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/AuthUtil.java index dcebc8f09e..125913fbe2 100644 --- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/AuthUtil.java +++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/AuthUtil.java @@ -191,7 +191,8 @@ public class AuthUtil { public static String getSignedRequestToken(String keystore, String storePass, String keyPass, String alias, int sigLifetime, String clientId, String realmInfoUrl) { - KeyPair keypair = KeystoreUtil.loadKeyPairFromKeystore(keystore, storePass, keyPass, alias, KeystoreUtil.KeystoreFormat.JKS); + KeystoreUtil.KeystoreFormat keystoreType = Enum.valueOf(KeystoreUtil.KeystoreFormat.class, KeystoreUtil.getKeystoreType(null, keystore, KeystoreUtil.KeystoreFormat.JKS.toString())); + KeyPair keypair = KeystoreUtil.loadKeyPairFromKeystore(keystore, storePass, keyPass, alias, keystoreType); JsonWebToken reqToken = new JsonWebToken(); reqToken.id(UUID.randomUUID().toString()); diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/AuthUtil.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/AuthUtil.java index 821271f96d..be0107b2da 100644 --- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/AuthUtil.java +++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/AuthUtil.java @@ -31,7 +31,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.security.KeyPair; -import java.security.PrivateKey; import java.util.UUID; import static java.lang.System.currentTimeMillis; @@ -193,7 +192,8 @@ public class AuthUtil { public static String getSignedRequestToken(String keystore, String storePass, String keyPass, String alias, int sigLifetime, String clientId, String realmInfoUrl) { - KeyPair keypair = KeystoreUtil.loadKeyPairFromKeystore(keystore, storePass, keyPass, alias, KeystoreUtil.KeystoreFormat.JKS); + KeystoreUtil.KeystoreFormat keystoreType = Enum.valueOf(KeystoreUtil.KeystoreFormat.class, KeystoreUtil.getKeystoreType(null, keystore, KeystoreUtil.KeystoreFormat.JKS.toString())); + KeyPair keypair = KeystoreUtil.loadKeyPairFromKeystore(keystore, storePass, keyPass, alias, keystoreType); JsonWebToken reqToken = new JsonWebToken(); reqToken.id(UUID.randomUUID().toString()); diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ClassLoaderPropertyMappers.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ClassLoaderPropertyMappers.java index 51368edfc1..c29b6eb3a1 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ClassLoaderPropertyMappers.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ClassLoaderPropertyMappers.java @@ -34,7 +34,7 @@ final class ClassLoaderPropertyMappers { if (fipsEnabled != null && FipsMode.valueOf(fipsEnabled.getValue()).isFipsEnabled()) { return Optional.of( - "org.bouncycastle:bcprov-jdk15on,org.bouncycastle:bcpkix-jdk15on,org.keycloak:keycloak-crypto-default"); + "org.bouncycastle:bcprov-jdk15on,org.bouncycastle:bcpkix-jdk15on,org.bouncycastle:bcutil-jdk15on,org.keycloak:keycloak-crypto-default"); } return Optional.of( diff --git a/testsuite/integration-arquillian/servers/auth-server/common/fips/kc.java.security b/testsuite/integration-arquillian/servers/auth-server/common/fips/kc.java.security index 3828ad81c5..c9d2d7d866 100644 --- a/testsuite/integration-arquillian/servers/auth-server/common/fips/kc.java.security +++ b/testsuite/integration-arquillian/servers/auth-server/common/fips/kc.java.security @@ -8,18 +8,19 @@ # List of providers and their preference orders (see above). Used on the host without FIPS (EG. when running the tests on GH actions) # Uses only BouncyCastle FIPS providers to make sure to use only FIPS compliant cryptography. # -security.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -security.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider fips:BCFIPS -security.provider.3= +#security.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider +#security.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider fips:BCFIPS +#security.provider.3= # # Security providers used when global crypto-policies are set to FIPS (Usually it is used when FIPS enabled on system/JVM level) # -fips.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -fips.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider fips:BCFIPS -fips.provider.3= -#fips.provider.3=SunJGSS -#fips.provider.4=XMLDSig +#fips.provider.1=SunPKCS11 ${java.home}/conf/security/nss.fips.cfg +#fips.provider.2=SUN +#fips.provider.3=SunEC +#fips.provider.4=com.sun.net.ssl.internal.ssl.Provider SunPKCS11-NSS-FIPS +#fips.provider.5=SunJGSS +#fips.provider.6=XMLDSig #fips.provider.5= # Commented this provider for now (and also other providers) as it uses lots of non-FIPS services. diff --git a/testsuite/integration-arquillian/servers/auth-server/quarkus/pom.xml b/testsuite/integration-arquillian/servers/auth-server/quarkus/pom.xml index 041692949c..e14ff9bc55 100644 --- a/testsuite/integration-arquillian/servers/auth-server/quarkus/pom.xml +++ b/testsuite/integration-arquillian/servers/auth-server/quarkus/pom.xml @@ -352,7 +352,7 @@ copy-dependencies - ${auth.server.home}/lib/bootstrap + ${auth.server.home}/providers bc-fips,bctls-fips,bcpkix-fips diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmTest.java index f202a3b0f3..6238b6bb5f 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmTest.java @@ -5,8 +5,10 @@ import org.junit.Test; import org.keycloak.client.admin.cli.config.ConfigData; import org.keycloak.client.admin.cli.config.FileConfigHandler; import org.keycloak.client.admin.cli.config.RealmConfigData; +import org.keycloak.common.util.KeystoreUtil; import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.testsuite.cli.KcAdmExec; +import org.keycloak.testsuite.util.KeystoreUtils; import org.keycloak.testsuite.util.TempFileResource; import org.keycloak.util.JsonSerialization; @@ -501,13 +503,24 @@ public class KcAdmTest extends AbstractAdmCliTest { } @Test - public void testCRUDWithOnTheFlyUserAuthWithSignedJwtClient() throws IOException { + public void testCRUDWithOnTheFlyUserAuthWithSignedJwtClient_JKSKeystore() throws IOException { + KeystoreUtils.assumeKeystoreTypeSupported(KeystoreUtil.KeystoreFormat.JKS); + testCRUDWithOnTheFlyUserAuthWithSignedJwtClient(KeystoreUtil.KeystoreFormat.JKS.getFileExtension()); + } + + @Test + public void testCRUDWithOnTheFlyUserAuthWithSignedJwtClient_PKCS12Keystore() throws IOException { + KeystoreUtils.assumeKeystoreTypeSupported(KeystoreUtil.KeystoreFormat.PKCS12); + testCRUDWithOnTheFlyUserAuthWithSignedJwtClient(KeystoreUtil.KeystoreFormat.PKCS12.getFileExtension()); + } + + private void testCRUDWithOnTheFlyUserAuthWithSignedJwtClient(String keystoreFileExtension) throws IOException { /* * Test create, get, update, and delete using on-the-fly authentication - without using any config file. * Login is performed by each operation again, and again using username, password, and client JWT signature. */ - File keystore = new File(System.getProperty("user.dir") + "/src/test/resources/cli/kcadm/admin-cli-keystore.jks"); - Assert.assertTrue("admin-cli-keystore.jks exists", keystore.isFile()); + File keystore = new File(System.getProperty("user.dir") + "/src/test/resources/cli/kcadm/admin-cli-keystore." + keystoreFileExtension); + Assert.assertTrue("admin-cli-keystore." + keystoreFileExtension + " must exist, but it does not exists", keystore.isFile()); // try client without direct grants enabled KcAdmExec exe = KcAdmExec.execute("get clients --no-config --server " + serverUrl + " --realm test" + @@ -536,7 +549,7 @@ public class KcAdmTest extends AbstractAdmCliTest { assertExitCodeAndStreamSizes(exe, 1, 0, 2); Assert.assertEquals("login message", "Logging into " + serverUrl + " as user user1 of realm test", exe.stderrLines().get(0)); - Assert.assertEquals("error message", "Failed to load private key: Keystore was tampered with, or password was incorrect", exe.stderrLines().get(exe.stderrLines().size() - 1)); + Assert.assertTrue("error message", exe.stderrLines().get(exe.stderrLines().size() - 1).startsWith("Failed to load private key:")); // try whole CRUD @@ -563,8 +576,8 @@ public class KcAdmTest extends AbstractAdmCliTest { * Test create, get, update, and delete using on-the-fly authentication - without using any config file. * Login is performed by each operation again, and again using only client JWT signature - service account is used. */ - File keystore = new File(System.getProperty("user.dir") + "/src/test/resources/cli/kcadm/admin-cli-keystore.jks"); - Assert.assertTrue("admin-cli-keystore.jks exists", keystore.isFile()); + File keystore = new File(System.getProperty("user.dir") + "/src/test/resources/cli/kcadm/admin-cli-keystore.p12"); + Assert.assertTrue("admin-cli-keystore.p12 exists", keystore.isFile()); testCRUDWithOnTheFlyAuth(serverUrl, "--client admin-cli-jwt --keystore '" + keystore.getAbsolutePath() + "' --storepass storepass --keypass keypass --alias admin-cli", "", diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTest.java index 83994d8f31..93a779c993 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTest.java @@ -6,8 +6,10 @@ import org.junit.Test; import org.keycloak.client.registration.cli.config.ConfigData; import org.keycloak.client.registration.cli.config.FileConfigHandler; import org.keycloak.client.registration.cli.config.RealmConfigData; +import org.keycloak.common.util.KeystoreUtil; import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.testsuite.cli.KcRegExec; +import org.keycloak.testsuite.util.KeystoreUtils; import org.keycloak.testsuite.util.TempFileResource; import org.keycloak.util.JsonSerialization; @@ -502,13 +504,24 @@ public class KcRegTest extends AbstractRegCliTest { } @Test - public void testCRUDWithOnTheFlyUserAuthWithSignedJwtClient() throws IOException { + public void testCRUDWithOnTheFlyUserAuthWithSignedJwtClient_JKSKeystore() throws IOException { + KeystoreUtils.assumeKeystoreTypeSupported(KeystoreUtil.KeystoreFormat.JKS); + testCRUDWithOnTheFlyUserAuthWithSignedJwtClient(KeystoreUtil.KeystoreFormat.JKS.getFileExtension()); + } + + @Test + public void testCRUDWithOnTheFlyUserAuthWithSignedJwtClient_PKCS12Keystore() throws IOException { + KeystoreUtils.assumeKeystoreTypeSupported(KeystoreUtil.KeystoreFormat.PKCS12); + testCRUDWithOnTheFlyUserAuthWithSignedJwtClient(KeystoreUtil.KeystoreFormat.PKCS12.getFileExtension()); + } + + private void testCRUDWithOnTheFlyUserAuthWithSignedJwtClient(String keystoreFileExtension) throws IOException { /* * Test create, get, update, and delete using on-the-fly authentication - without using any config file. * Login is performed by each operation again, and again using username, password, and client JWT signature. */ - File keystore = new File(System.getProperty("user.dir") + "/src/test/resources/cli/kcreg/reg-cli-keystore.jks"); - Assert.assertTrue("reg-cli-keystore.jks exists", keystore.isFile()); + File keystore = new File(System.getProperty("user.dir") + "/src/test/resources/cli/kcreg/reg-cli-keystore." + keystoreFileExtension); + Assert.assertTrue("reg-cli-keystore." + keystoreFileExtension + " exists", keystore.isFile()); // try client without direct grants enabled KcRegExec exe = execute("get test-client --no-config --server " + serverUrl + " --realm test" + @@ -537,7 +550,7 @@ public class KcRegTest extends AbstractRegCliTest { assertExitCodeAndStreamSizes(exe, 1, 0, 2); Assert.assertEquals("login message", "Logging into " + serverUrl + " as user user1 of realm test", exe.stderrLines().get(0)); - Assert.assertEquals("error message", "Failed to load private key: Keystore was tampered with, or password was incorrect", exe.stderrLines().get(exe.stderrLines().size() - 1)); + Assert.assertTrue("error message", exe.stderrLines().get(exe.stderrLines().size() - 1).startsWith("Failed to load private key: ")); // try whole CRUD @@ -564,8 +577,8 @@ public class KcRegTest extends AbstractRegCliTest { * Test create, get, update, and delete using on-the-fly authentication - without using any config file. * Login is performed by each operation again, and again using only client JWT signature - service account is used. */ - File keystore = new File(System.getProperty("user.dir") + "/src/test/resources/cli/kcreg/reg-cli-keystore.jks"); - Assert.assertTrue("reg-cli-keystore.jks exists", keystore.isFile()); + File keystore = new File(System.getProperty("user.dir") + "/src/test/resources/cli/kcreg/reg-cli-keystore.p12"); + Assert.assertTrue("reg-cli-keystore.p12 exists", keystore.isFile()); testCRUDWithOnTheFlyAuth(serverUrl, "--client reg-cli-jwt --keystore '" + keystore.getAbsolutePath() + "' --storepass storepass --keypass keypass --alias reg-cli", "", diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/cli/kcadm/admin-cli-keystore.p12 b/testsuite/integration-arquillian/tests/base/src/test/resources/cli/kcadm/admin-cli-keystore.p12 new file mode 100644 index 0000000000000000000000000000000000000000..c05dd0f55f5de53565671648ac2b70adb6f270d4 GIT binary patch literal 2526 zcma)8S5y-S7EMAzks=eRK@bRCU=mz>`??0)Tjyz|bx_uc#V?s*6j*CYtYh9GezvU4dVnI~=Y z0y%)CB(88Ui7VtM9Ec!6p8XdEsQ{B84}QW$KkFVl_rFy<$AF+x66EYp@C?HDmjc3z za71YRJ@OzS=|D1`z&EH^CLUjEY`|lHY zT^6I&n~&~v>y66ne$&Ci8o#K^m;T0Vih0jD6aNCYcGybZxN^{nu)K9^lql_nlDBI~ z#4voS{Q{8*#Sbc-wZ&-H=g^(GjiNJ>gk=zZoN-m|gN5^`a{EPmkj#pCUH0xbCB;FB z$Xbm5N^Pb;F6l?%Ip^CP3V%?N?oP(}UN}x!TPByhII!)^U5`o{7wV0ia%;vosohNtnz;H}kCxvexL1$4UZbWgFVY zXA`-HgOQie={l3l+n#Jz>d=zG4LVNzn$x3uV9^u&ek1SL<$LZ@)h#b>R-H zVfM@4$;}L9_p9Myt91Q|4@p?s5nKW?eXD0k=Y``_d6tZL!|t|OZIDdK{T7j~*l~?( zUV>8V-JHBIhlj46P0=ex_m)FyDy<&t=XJfby#!;`&Bs&bC8d;ziBWJpJj(~kEzzGo zr|3F%LiKn5`ZUsa_!HmCR+#Q2Rcz#Dc_G^Bb-rp?4$juWA^_rc#W*(fqi#c~vauRw z&*@cxv(VU^r7^l~nPwIt|9(hj+()YQ;SJB_DB`!25q9=I@?qT!7(Lp5J|1d0*4!4Q zUc`#2>Ha)nmv}0Oh1Zfd_7LIBR7*isBW)a{!*z|q)==o?>eQ~qgJ=G98TXpBO+GaC zq^_{vL!B|Dd1QU=N2sY~6k+v5a9aq{pfjN2KB7^V9|aA=@1ohv-S_TD=a!VVj>1+G z&@=b4NFe(mF1a$a*H}DH^x|&MbyF%yr8*GsU9!XPAor^t$gdt*>*hI&T_}nfkOhtqPvCbh%i){`b5Zu17{H`oR zcOlY8iCl3jwzZNtzI)W6-zg63F!UKzC8$RjRsUdnMdu#YGoeK%2Mexn3}dTwH|;C)_e)+8lPN_8zo2y&c~; z?>f4lrf>TyF@1CUFOqoflakxU=kHi);xmlAH@x5X&TQ9?{5iv`sajvmd=M-3B}URt zbN~Y8Rd3`v)$V%alk_n-kA~5u8g}8_A|kj`9)H0y+%T*RntSQSU-@Av(I=h_P1}El z!&De#Z1Hy?5GJZe^T|oJA6e<+xg`7U%=3;PT-7R{M zu^L!+^o<`^sGo+5AmQO$OO=3P>I;i<_7_>{9R;1#WTVYt;73C>xh+FTLeq?JK9TUC z(*3ad)rxg73q7;nSItLYSjk0Z$TTcEP&|%GiEh;CEPUJd9TQ3i`8FWVvogx@DBwsh zp0g(AO!9<K|-wg17g*CCWmQ0hV`pU8OLV8lbE+|4z zTjT!;Yb*Fuo<>*#Ycg`7Qg}KrCyvA>39Y5&MF#rWVt2&^b*n&W&r_KzW^b_{T@(-S zIN5kS^->b;K7$dy%fPkc6?%F`y_c@*{r*OTSd?m}=x7G^cgTZ!Lgg?u+Vug%t?Qn_ zy$eE*&d5zCwWj0j2t9tY(Jx!OrTAoxGX=#|Z~T(qWnGg)FKBFh%h7vq7&VA%_|QgM`toOU%6yydJHq7;PrMn^XEk@#PHx!6+$0yX z|3$d)BQ)Vr&5{RdKwooVLruN#!DY|k@?0*fktZ@Xhy`H0oZ5(#DhJ7*t0f;m83eQTrScvb}#ZW~sasy`ehNztLWn zSa?M`z2$(|cF7ZbnfmG(HN9ktHeeOz^}k^0O7VeFG}x4hnT`7$mz zBH35=h{3kG5fGPp>`yx9sr;|aos%MQcCN6bCVhz0CU+!Oz>d)Fk%;!Ww}@@c#OF zKtKopEIGD{Nlx7Q^q4^k*}ulLEY&iDP&`~2{eueWJJ>=P7Azp!{pB!x0xce1*t0bC Onn~00?>YC+6a5GK>x)qU literal 0 HcmV?d00001 diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/cli/kcreg/reg-cli-keystore.p12 b/testsuite/integration-arquillian/tests/base/src/test/resources/cli/kcreg/reg-cli-keystore.p12 new file mode 100644 index 0000000000000000000000000000000000000000..1e165a5379a1887ff8f1798c244c7fe4be077676 GIT binary patch literal 2522 zcma);c{JOJ7RM8^2%(wQHmJsy5UM}54?1W|Os$PlQd^7?4Z2vSs+QRIYLHs08f%BD z*r~lrv`>oKY8|`ATG}d#XU>~5bKYO?{c+Dd_xru~{&zp;0#w8h7nmEMB0^yZTogWP zn;#4Z=TZ^3AXJ3ckxT}t(DMJXpid!G=;I?f<0#T#e1AGdjiT2 z*a2Gqlt@4kA}Igy(Knon-I`O%KL0|Dk=bW-w>}pa7R3cd14tOpe>QRtb?|WOU2HHFNgt$u8D22o=&B#OriO7tL8C$9~~nSa!AC?fqO-xIHCd z*DmcK$@O&aTo0Bh;}O3V*$PUrn{mRYi>ZI`5N;8G`eEJYB{;trH_-ww+6=?Cev=tfBltaI9xLRwEqG3f{j@i17m zba$9vK9g_KmZBK&)3aDtN~z$JvRtJ1aJ@*z+A}ez2(wY%+j>e0fX`U{nKQa7KiqKrJZxf|mszvf{jd9(f$sBI?d*Nf%)4SHbB?}`8uEE0?a>xOO1>DB4zM0-xcMz-dueI|k8j=TE zZyClV?8{PeeR_Gf8+~Nly3JI#B0k!?YY5K!5Qz)HenyC zFMlFcV+dBt363t~r~7jYc^1=9OSM}Q28%m0#v+|`=~xXNy}d$Dd=EoEf2Bced!tqK zUBLIcRF`9qb3Q+^)!cpG?L|o7J2&U8pFCtDVu4L{sLBxAHYoU)uCR~4`oGvo+Kvq3 z#ndY^Wx}Jvwl{-P96CygI`$(KVrF}Xqi>T+>v&v(BQ<~F&t31~>JNLbzwL*f`5Lv-#R<7^_9^ch*>9vD^vW#WmuZ?4hBoL=)TNURPPWY*V4tEN4 zG2DOc7=bwP1Tq{>7wS<4i z9SA-VZTgM3J;EXe=IkAk6&EptOsg*?M|(tEURdQ5_jVh zLTID@_`HU}WzGvG7^<>R%S*}6azwQnG^q3qiw^F%>kW|NT_vkd{k-YoF3C6 z`~QIY4~|y#wrRV;o$)WyG~jq*PljKMVz zlOr}ZKFXtCTD7Dd1ZV%m8!}iwuKrl$*qJF-h^t<+9*<3m_Rxtb<#dY@mXOxRReYb| ziTJ^aZ>UMf=Mx*=t?SXhuK62OABvlD@18`ey_#2zP`waMxprHLK-Ik;!LI9ER9#Zv zeDLVZX!EryHwDK9!2NOt*Wu6o1H{$oAo9dy|S>Z~9b+t16v# z`GuscRP0E}ijYcvQ7mjmUwvWeyv1@9WXlYM0I`MW_1Vlaw?Fu!)PYpkUT?=0p4~jT zzU)C&na{ z&Yc5f%;2){iNJ!Zn)Uk7e8J8cW&0lS^651pi>(GXz}U^=teiGT#XVXAwy5q}$JU&D zHov-3s*Fb`5M}DM6{d7+QVRE0jGVel1fEj>L9`Z84JqD@WkkC#hs}5rF~We#@Arsl z6-fk!ecs}^4&JG&XW&4N4QBloNiW^$tQE3x+!wW+vjk zG!)DyrNEUh17$aFAgBM*xi^nDoZ?YPQZTDyZic^7n=@;Z*bi$)5l`)97u;_m)d&KC zNewmNx9hJpx%1F8?!Xbu`_$yY3(QCdZT5~33)es2cC(Ka-3gS-$cbMZSk|+eo7AD{ z!_rRT;^>ML`?7HTc_q8zyM1HkMXhlM3{lU1B|g*3mns2s1?&aD3{V01|NeKlz)%nb zy#jp1iTRt97V1o@D(}9*uq%!w7VNrMVd8SaMyk1eAcE(`na9`Rnkd?|9$#aEBkPXQ J1&u#X^xyJcjcot` literal 0 HcmV?d00001