diff --git a/adapters/saml/core/pom.xml b/adapters/saml/core/pom.xml index ac557d82973..0abc9941205 100755 --- a/adapters/saml/core/pom.xml +++ b/adapters/saml/core/pom.xml @@ -61,6 +61,16 @@ keycloak-common provided + + org.bouncycastle + bcprov-jdk18on + provided + + + org.bouncycastle + bcpkix-jdk18on + provided + org.jboss.logging jboss-logging diff --git a/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/config/PemUtils.java b/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/config/PemUtils.java index d60d1e39228..8b9b0f3cec9 100644 --- a/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/config/PemUtils.java +++ b/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/config/PemUtils.java @@ -26,15 +26,19 @@ import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; +import java.security.Provider; import java.security.PublicKey; +import java.security.Security; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.jboss.logging.Logger; +import org.keycloak.common.crypto.CryptoConstants; import org.keycloak.common.util.Base64; -import org.keycloak.common.util.BouncyIntegration; import org.keycloak.common.util.PemException; /** @@ -42,6 +46,20 @@ import org.keycloak.common.util.PemException; */ public class PemUtils { + private static final Logger log = Logger.getLogger(PemUtils.class); + + static { + Provider existingBc = Security.getProvider(CryptoConstants.BC_PROVIDER_ID); + Provider bcProvider = existingBc == null ? new BouncyCastleProvider() : existingBc; + + if (existingBc == null) { + Security.addProvider(bcProvider); + log.debugv("Loaded {0} security provider", bcProvider.getClass().getName()); + } else { + log.debugv("Security provider {0} already loaded", bcProvider.getClass().getName()); + } + } + /** * Decode a X509 Certificate from a PEM string * @@ -124,12 +142,12 @@ public class PemUtils { private static PrivateKey decodePrivateKey(byte[] der) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException { PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(der); - KeyFactory kf = KeyFactory.getInstance("RSA", BouncyIntegration.PROVIDER); + KeyFactory kf = KeyFactory.getInstance("RSA", CryptoConstants.BC_PROVIDER_ID); return kf.generatePrivate(spec); } private static X509Certificate decodeCertificate(InputStream is) throws Exception { - CertificateFactory cf = CertificateFactory.getInstance("X.509", BouncyIntegration.PROVIDER); + CertificateFactory cf = CertificateFactory.getInstance("X.509", CryptoConstants.BC_PROVIDER_ID); X509Certificate cert = (X509Certificate) cf.generateCertificate(is); is.close(); return cert; @@ -138,7 +156,7 @@ public class PemUtils { private static PublicKey decodePublicKey(byte[] der, String type) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException { X509EncodedKeySpec spec = new X509EncodedKeySpec(der); - KeyFactory kf = KeyFactory.getInstance("RSA", BouncyIntegration.PROVIDER); + KeyFactory kf = KeyFactory.getInstance("RSA", CryptoConstants.BC_PROVIDER_ID); return kf.generatePublic(spec); } } diff --git a/adapters/saml/core/src/test/java/org/keycloak/adapters/saml/DeploymentBuilderTest.java b/adapters/saml/core/src/test/java/org/keycloak/adapters/saml/DeploymentBuilderTest.java new file mode 100644 index 00000000000..993b71a11dc --- /dev/null +++ b/adapters/saml/core/src/test/java/org/keycloak/adapters/saml/DeploymentBuilderTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * 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.adapters.saml; + +import java.io.InputStream; + +import org.junit.Assert; +import org.junit.Test; +import org.keycloak.adapters.saml.config.parsers.DeploymentBuilder; +import org.keycloak.adapters.saml.config.parsers.ResourceLoader; + +/** + * @author Marek Posolda + */ +public class DeploymentBuilderTest { + + @Test + public void testPropertiesBasedRoleMapper() throws Exception { + InputStream is = getClass().getResourceAsStream("config/parsers/keycloak-saml-pem-keys.xml"); + SamlDeployment deployment = new DeploymentBuilder().build(is, new ResourceLoader() { + @Override + public InputStream getResourceAsStream(String resource) { + return this.getClass().getClassLoader().getResourceAsStream(resource); + } + }); + Assert.assertNotNull(deployment); + Assert.assertNotNull(deployment.getSigningKeyPair().getPrivate()); + Assert.assertNotNull(deployment.getSigningKeyPair().getPublic()); + } +} diff --git a/adapters/saml/core/src/test/resources/keystores/keystore.jks b/adapters/saml/core/src/test/resources/keystores/keystore.jks new file mode 100755 index 00000000000..5554f13323d Binary files /dev/null and b/adapters/saml/core/src/test/resources/keystores/keystore.jks differ diff --git a/adapters/saml/core/src/test/resources/org/keycloak/adapters/saml/config/parsers/keycloak-saml-pem-keys.xml b/adapters/saml/core/src/test/resources/org/keycloak/adapters/saml/config/parsers/keycloak-saml-pem-keys.xml new file mode 100644 index 00000000000..1a843cffe5e --- /dev/null +++ b/adapters/saml/core/src/test/resources/org/keycloak/adapters/saml/config/parsers/keycloak-saml-pem-keys.xml @@ -0,0 +1,67 @@ + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/employee-sig/WEB-INF/keycloak-saml.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/employee-sig/WEB-INF/keycloak-saml.xml index 6b63834cd3a..9e053f7d049 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/employee-sig/WEB-INF/keycloak-saml.xml +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/employee-sig/WEB-INF/keycloak-saml.xml @@ -25,10 +25,12 @@ forceAuthentication="false"> - - - - + + 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 +