View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.core.persistence.jpa.inner;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  
26  import java.io.ByteArrayInputStream;
27  import java.io.ByteArrayOutputStream;
28  import java.math.BigInteger;
29  import java.security.KeyPair;
30  import java.security.KeyPairGenerator;
31  import java.security.KeyStore;
32  import java.security.Signature;
33  import java.security.cert.Certificate;
34  import java.security.cert.CertificateFactory;
35  import java.util.Date;
36  import java.util.UUID;
37  import org.apache.commons.io.IOUtils;
38  import org.apache.syncope.core.persistence.api.dao.SAML2SPEntityDAO;
39  import org.apache.syncope.core.persistence.api.entity.am.SAML2SPEntity;
40  import org.apache.syncope.core.persistence.jpa.AbstractTest;
41  import org.bouncycastle.asn1.ASN1EncodableVector;
42  import org.bouncycastle.asn1.ASN1Encoding;
43  import org.bouncycastle.asn1.ASN1Integer;
44  import org.bouncycastle.asn1.DERBitString;
45  import org.bouncycastle.asn1.DERNull;
46  import org.bouncycastle.asn1.DERSequence;
47  import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
48  import org.bouncycastle.asn1.x500.X500Name;
49  import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
50  import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
51  import org.bouncycastle.asn1.x509.TBSCertificate;
52  import org.bouncycastle.asn1.x509.Time;
53  import org.bouncycastle.asn1.x509.V3TBSCertificateGenerator;
54  import org.junit.jupiter.api.Test;
55  import org.springframework.beans.factory.annotation.Autowired;
56  import org.springframework.core.io.ClassPathResource;
57  import org.springframework.transaction.annotation.Transactional;
58  
59  @Transactional("Master")
60  public class SAML2SPEntityTest extends AbstractTest {
61  
62      private static Certificate createSelfSignedCert(final KeyPair keyPair) throws Exception {
63          X500Name dn = new X500Name("cn=Unknown");
64          V3TBSCertificateGenerator certGen = new V3TBSCertificateGenerator();
65  
66          certGen.setSerialNumber(new ASN1Integer(BigInteger.valueOf(1)));
67          certGen.setIssuer(dn);
68          certGen.setSubject(dn);
69          certGen.setStartDate(new Time(new Date(System.currentTimeMillis() - 1000L)));
70  
71          Date expiration = new Date(System.currentTimeMillis() + 100000);
72          certGen.setEndDate(new Time(expiration));
73  
74          AlgorithmIdentifier sigAlgID = new AlgorithmIdentifier(
75                  PKCSObjectIdentifiers.sha1WithRSAEncryption, DERNull.INSTANCE);
76          certGen.setSignature(sigAlgID);
77          certGen.setSubjectPublicKeyInfo(SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()));
78  
79          Signature sig = Signature.getInstance("SHA1WithRSA");
80          sig.initSign(keyPair.getPrivate());
81          sig.update(certGen.generateTBSCertificate().getEncoded(ASN1Encoding.DER));
82  
83          TBSCertificate tbsCert = certGen.generateTBSCertificate();
84          ASN1EncodableVector v = new ASN1EncodableVector();
85  
86          v.add(tbsCert);
87          v.add(sigAlgID);
88          v.add(new DERBitString(sig.sign()));
89  
90          Certificate cert = CertificateFactory.getInstance("X.509").
91                  generateCertificate(new ByteArrayInputStream(new DERSequence(v).getEncoded(ASN1Encoding.DER)));
92          cert.verify(keyPair.getPublic());
93          return cert;
94      }
95  
96      @Autowired
97      private SAML2SPEntityDAO saml2SPEntityDAO;
98  
99      @Test
100     public void find() throws Exception {
101         create("Syncope");
102         SAML2SPEntity entity = saml2SPEntityDAO.find("Syncope");
103         assertNotNull(entity);
104 
105         entity = saml2SPEntityDAO.find(UUID.randomUUID().toString());
106         assertNull(entity);
107     }
108 
109     @Test
110     public void save() throws Exception {
111         SAML2SPEntity created = create("SyncopeCreate");
112 
113         KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
114         char[] pwdArray = "password".toCharArray();
115         ks.load(new ByteArrayInputStream(created.getKeystore()), pwdArray);
116         assertTrue(ks.size() > 0);
117     }
118 
119     @Test
120     public void update() throws Exception {
121         SAML2SPEntity entity = create("SyncopeUpdate");
122         assertNotNull(entity);
123         entity.setKey("OtherSyncope");
124 
125         entity = saml2SPEntityDAO.save(entity);
126         assertNotNull(entity);
127 
128         entityManager().flush();
129 
130         SAML2SPEntity found = saml2SPEntityDAO.find(entity.getKey());
131         assertNotNull(found);
132         assertEquals("OtherSyncope", found.getKey());
133     }
134 
135     private SAML2SPEntity create(final String owner) throws Exception {
136         SAML2SPEntity entity = entityFactory.newEntity(SAML2SPEntity.class);
137         entity.setKey(owner);
138         entity.setMetadata(IOUtils.toByteArray(new ClassPathResource("sp-metadata.xml").getInputStream()));
139 
140         KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
141         char[] pwdArray = "password".toCharArray();
142         ks.load(null, pwdArray);
143 
144         KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
145         keyPairGenerator.initialize(4096);
146         KeyPair keyPair = keyPairGenerator.generateKeyPair();
147         Certificate certificate = createSelfSignedCert(keyPair);
148         ks.setKeyEntry("main", keyPair.getPrivate(), "password".toCharArray(), new Certificate[] { certificate });
149 
150         try (ByteArrayOutputStream fos = new ByteArrayOutputStream()) {
151             ks.store(fos, pwdArray);
152             fos.flush();
153             entity.setKeystore(fos.toByteArray());
154         }
155         assertNotNull(entity.getKeystore());
156 
157         entity = saml2SPEntityDAO.save(entity);
158         assertNotNull(saml2SPEntityDAO.find(entity.getKey()));
159         return entity;
160     }
161 }