You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by co...@apache.org on 2017/08/11 12:15:14 UTC

[2/3] syncope git commit: Dynamically generate a keypair for use in the SAML signing tests

Dynamically generate a keypair for use in the SAML signing tests


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/d8d5fe5e
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/d8d5fe5e
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/d8d5fe5e

Branch: refs/heads/master
Commit: d8d5fe5ee8c7e887f5c2fda8362aa9a0296635c9
Parents: a22a6b5
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Fri Aug 11 12:38:06 2017 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Fri Aug 11 13:15:07 2017 +0100

----------------------------------------------------------------------
 fit/core-reference/pom.xml                      |   7 ++
 .../apache/syncope/fit/core/SAML2ITCase.java    | 104 +++++++++++++++++--
 fit/core-reference/src/test/resources/fediz.xml |  14 +--
 pom.xml                                         |   2 +
 4 files changed, 108 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/d8d5fe5e/fit/core-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/pom.xml b/fit/core-reference/pom.xml
index 5762a33..45a6214 100644
--- a/fit/core-reference/pom.xml
+++ b/fit/core-reference/pom.xml
@@ -176,6 +176,13 @@ under the License.
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcpkix-jdk15on</artifactId>
+      <version>${bouncycastle.version}</version>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
 
   <build>

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8d5fe5e/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SAML2ITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SAML2ITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SAML2ITCase.java
index 93608c2..9ee5653 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SAML2ITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SAML2ITCase.java
@@ -26,12 +26,23 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.io.File;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.math.BigInteger;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
 import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.Collections;
+import java.util.Date;
 import java.util.Optional;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
@@ -71,6 +82,13 @@ import org.apache.wss4j.common.util.Loader;
 import org.apache.wss4j.dom.WSConstants;
 import org.apache.wss4j.dom.engine.WSSConfig;
 import org.apache.xml.security.signature.XMLSignature;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.style.RFC4519Style;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
 import org.joda.time.DateTime;
 import org.junit.AfterClass;
 import org.junit.Assume;
@@ -85,6 +103,8 @@ import org.w3c.dom.Element;
 public class SAML2ITCase extends AbstractITCase {
 
     private static SyncopeClient anonymous;
+    private static Path keystorePath;
+    private static Path truststorePath;
 
     @BeforeClass
     public static void setup() {
@@ -97,13 +117,17 @@ public class SAML2ITCase extends AbstractITCase {
     }
 
     @BeforeClass
-    public static void importFromIdPMetadata() {
+    public static void importFromIdPMetadata() throws Exception {
         if (!SAML2SPDetector.isSAML2SPAvailable()) {
             return;
         }
 
         assertTrue(saml2IdPService.list().isEmpty());
 
+        createKeystores();
+
+        updateMetadataWithCert();
+
         WebClient.client(saml2IdPService).
                 accept(MediaType.APPLICATION_XML_TYPE).
                 type(MediaType.APPLICATION_XML_TYPE);
@@ -123,7 +147,7 @@ public class SAML2ITCase extends AbstractITCase {
     }
 
     @AfterClass
-    public static void clearIdPs() {
+    public static void clearIdPs() throws Exception {
         if (!SAML2SPDetector.isSAML2SPAvailable()) {
             return;
         }
@@ -131,6 +155,9 @@ public class SAML2ITCase extends AbstractITCase {
         for (SAML2IdPTO idp : saml2IdPService.list()) {
             saml2IdPService.delete(idp.getKey());
         }
+
+        Files.delete(keystorePath);
+        Files.delete(truststorePath);
     }
 
     @Test
@@ -409,16 +436,81 @@ public class SAML2ITCase extends AbstractITCase {
         if (signAssertion) {
             Crypto issuerCrypto = new Merlin();
             KeyStore keyStore = KeyStore.getInstance("JKS");
-            ClassLoader loader = Loader.getClassLoader(getClass());
-            InputStream input = Merlin.loadInputStream(loader, "keystore");
-            keyStore.load(input, "changeit".toCharArray());
+            InputStream input = Files.newInputStream(keystorePath);
+            keyStore.load(input, "security".toCharArray());
             ((Merlin) issuerCrypto).setKeyStore(keyStore);
 
-            assertion.signAssertion("sp", "changeit", issuerCrypto, false);
+            assertion.signAssertion("subject", "security", issuerCrypto, false);
         }
 
         response.getAssertions().add(assertion.getSaml2());
 
         return response;
     }
+
+    private static void createKeystores() throws Exception {
+        // Create KeyPair
+        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+        keyPairGenerator.initialize(1024, new SecureRandom());
+        KeyPair keyPair = keyPairGenerator.generateKeyPair();
+
+        Date currentDate = new Date();
+        Date expiryDate = new Date(currentDate.getTime() + 365L * 24L * 60L * 60L * 1000L);
+
+        // Create X509Certificate
+        String issuerName = "CN=Issuer";
+        String subjectName = "CN=Subject";
+        BigInteger serial = new BigInteger("123456");
+        X509v3CertificateBuilder certBuilder =
+                        new X509v3CertificateBuilder(new X500Name(RFC4519Style.INSTANCE, issuerName), serial, currentDate, expiryDate,
+                                        new X500Name(RFC4519Style.INSTANCE, subjectName),
+                                        SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()));
+        ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSAEncryption").build(keyPair.getPrivate());
+        X509Certificate certificate = new JcaX509CertificateConverter().getCertificate(certBuilder.build(contentSigner));
+
+        // Store Private Key + Certificate in Keystore
+        KeyStore keystore = KeyStore.getInstance("JKS");
+        keystore.load(null, "security".toCharArray());
+        keystore.setKeyEntry("subject", keyPair.getPrivate(), "security".toCharArray(), new Certificate[] {certificate});
+
+        File keystoreFile = File.createTempFile("samlkeystore", ".jks");
+        try (OutputStream output = Files.newOutputStream(keystoreFile.toPath())) {
+            keystore.store(output, "security".toCharArray());
+        }
+        keystorePath = keystoreFile.toPath();
+
+        // Now store the Certificate in the truststore
+        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
+        trustStore.load(null, "security".toCharArray());
+
+        trustStore.setCertificateEntry("subject", certificate);
+
+        File truststoreFile = File.createTempFile("samltruststore", ".jks");
+        try (OutputStream output = Files.newOutputStream(truststoreFile.toPath())) {
+            trustStore.store(output, "security".toCharArray());
+        }
+        truststorePath = truststoreFile.toPath();
+    }
+
+    private static void updateMetadataWithCert() throws Exception {
+        // Get encoded truststore cert
+        KeyStore keyStore = KeyStore.getInstance("JKS");
+        InputStream input = Files.newInputStream(truststorePath);
+        keyStore.load(input, "security".toCharArray());
+        X509Certificate cert = (X509Certificate)keyStore.getCertificate("subject");
+        String certEncoded = java.util.Base64.getMimeEncoder().encodeToString(cert.getEncoded());
+
+        // Replace the "cert-placeholder" string in the metadata with the actual cert
+        String basedir = System.getProperty("basedir");
+        if (basedir == null) {
+            basedir = new File(".").getCanonicalPath();
+        }
+        Path path = FileSystems.getDefault().getPath(basedir, "/src/test/resources/fediz.xml");
+        String content = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
+        content = content.replaceAll("cert-placeholder", certEncoded);
+
+        Path path2 = FileSystems.getDefault().getPath(basedir, "/target/test-classes/fediz.xml");
+        Files.write(path2, content.getBytes());
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8d5fe5e/fit/core-reference/src/test/resources/fediz.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/fediz.xml b/fit/core-reference/src/test/resources/fediz.xml
index cbc8faa..b8cbda0 100644
--- a/fit/core-reference/src/test/resources/fediz.xml
+++ b/fit/core-reference/src/test/resources/fediz.xml
@@ -23,19 +23,7 @@ under the License.
             <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                 <ds:X509Data>
                     <ds:X509Certificate>
-MIICwTCCAamgAwIBAgIEINqJ9TANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDEwZSRUFMTUEwHhcN
-MTUwNjEwMTU0NDE3WhcNMjUwNDE4MTU0NDE3WjARMQ8wDQYDVQQDEwZSRUFMTUEwggEiMA0GCSqG
-SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCJDSXn2lDR+JM+AsJarFG3/XGH7K+9AfAbQIz2IgB9MCpO
-KVWTUPCvuo1I+Fp5nEGreuHYLEwgIiam3o+C9tvpLgtDDaDkmXjDzkWpk8z6+im72HZ/ODF93Rqw
-jIiY5ZCzgDumFyPzdKiGwChThamidy+rd6oheSoi6qRVSMMcnwiEUmvkfFvV3izXRqeT5nGQwsin
-y9mCEiGx8jkfxP++H0RQjVjhOwzfQ7epsR7dTQNf2ZhkBR3o6wKV9QnF2IBWHZpA9EK58rWU9H6j
-G7b631rYvwsbOUF9HcZ8DI2BFh+4p18jDN/fnjNGSLr9rYOExpsIiF1cHBK7Tr7WwCmDAgMBAAGj
-ITAfMB0GA1UdDgQWBBRHy0qYoLm9jx/1L6r61NznHKun2jANBgkqhkiG9w0BAQsFAAOCAQEAR9rU
-5Sp1FsOErdvKNFqeaKl0oq6Fuz7BWcGm2kK6+1ZbWE8IOv6Vh+BlLuOe5hF7aLUbm8UIjhKsmg0M
-Ey5MBwkBZktT1qhQteMuiKgYR7CxayCxO0f125RYvvwntJa5rI7bUrzOqX29VQD1qQ/Tb+08fULT
-L7oURP+g88Ff99dn3IpO4VZxZdsbl4+KZRtqQvPAdXNYjOajJtPzS489+/DtfWJ6wPm/7YZ4did4
-1fYcrdwyEZ15L0/5i931z7sztNickm5WhO40qEVDKN6KrlV2Eyea0+933v2Pwe4resTlko9G2T5h
-dEaSbvht2Q/JOMMmT91daeto2oS8HTKhTA==
+cert-placeholder
                    </ds:X509Certificate>
                 </ds:X509Data>
             </ds:KeyInfo>

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8d5fe5e/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index fdd22f2..b3eb5e5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -356,6 +356,8 @@ under the License.
   <properties>
     <syncope.version>${project.version}</syncope.version>
 
+    <bouncycastle.version>1.57</bouncycastle.version>
+
     <connid.version>1.4.3.0</connid.version>
     <connid.soap.version>1.4.2-SNAPSHOT</connid.soap.version>
     <connid.rest.version>1.0.1</connid.rest.version>