[OOM CERT-SERVICE-API] Add support for URI, IP, E-mail in SANs
[oom/platform/cert-service.git] / certService / src / test / java / org / onap / oom / certservice / cmpv2client / Cmpv2ClientTest.java
1 /*
2  * Copyright (C) 2019 Ericsson Software Technology AB. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16
17 package org.onap.oom.certservice.cmpv2client;
18
19 import static org.junit.jupiter.api.Assertions.assertNotNull;
20 import static org.mockito.ArgumentMatchers.any;
21 import static org.mockito.Mockito.doAnswer;
22 import static org.mockito.Mockito.spy;
23 import static org.mockito.Mockito.when;
24 import static org.mockito.MockitoAnnotations.initMocks;
25
26 import java.io.BufferedInputStream;
27 import java.io.ByteArrayOutputStream;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.OutputStream;
31 import java.security.KeyFactory;
32 import java.security.KeyPair;
33 import java.security.NoSuchAlgorithmException;
34 import java.security.NoSuchProviderException;
35 import java.security.PrivateKey;
36 import java.security.PublicKey;
37 import java.security.Security;
38 import java.security.cert.X509Certificate;
39 import java.security.spec.InvalidKeySpecException;
40 import java.security.spec.PKCS8EncodedKeySpec;
41 import java.security.spec.X509EncodedKeySpec;
42 import java.text.ParseException;
43 import java.text.SimpleDateFormat;
44 import java.util.Collections;
45 import java.util.Date;
46 import java.util.List;
47
48 import org.apache.commons.io.IOUtils;
49 import org.apache.http.HttpEntity;
50 import org.apache.http.client.methods.CloseableHttpResponse;
51 import org.apache.http.impl.client.CloseableHttpClient;
52 import org.bouncycastle.asn1.x500.X500Name;
53 import org.bouncycastle.asn1.x500.X500NameBuilder;
54 import org.bouncycastle.asn1.x500.style.BCStyle;
55 import org.bouncycastle.asn1.x509.GeneralName;
56 import org.bouncycastle.jce.provider.BouncyCastleProvider;
57 import org.junit.jupiter.api.Assertions;
58 import org.junit.jupiter.api.BeforeEach;
59 import org.junit.jupiter.api.Test;
60 import org.mockito.Mock;
61 import org.onap.oom.certservice.certification.configuration.model.Authentication;
62 import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server;
63 import org.onap.oom.certservice.certification.model.CsrModel;
64 import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException;
65 import org.onap.oom.certservice.cmpv2client.impl.CmpClientImpl;
66 import org.onap.oom.certservice.cmpv2client.model.Cmpv2CertificationModel;
67
68 class Cmpv2ClientTest {
69
70     static {
71         Security.addProvider(new BouncyCastleProvider());
72     }
73
74     private CsrModel csrModel;
75     private Cmpv2Server server;
76     private Date notBefore;
77     private Date notAfter;
78     private X500Name dn;
79
80     @Mock
81     X509Certificate cert;
82
83     @Mock
84     CloseableHttpClient httpClient;
85
86     @Mock
87     CloseableHttpResponse httpResponse;
88
89     @Mock
90     HttpEntity httpEntity;
91
92     private static KeyPair keyPair;
93
94     @BeforeEach
95     void setUp()
96             throws NoSuchProviderException, NoSuchAlgorithmException, IOException,
97             InvalidKeySpecException {
98         keyPair = loadKeyPair();
99         dn = new X500NameBuilder()
100                 .addRDN(BCStyle.O, "TestOrganization")
101                 .build();
102         initMocks(this);
103     }
104
105     public KeyPair loadKeyPair()
106             throws IOException, NoSuchAlgorithmException, InvalidKeySpecException,
107             NoSuchProviderException {
108
109         final InputStream privateInputStream = this.getClass().getResourceAsStream("/privateKey");
110         final InputStream publicInputStream = this.getClass().getResourceAsStream("/publicKey");
111         BufferedInputStream bis = new BufferedInputStream(privateInputStream);
112         byte[] privateBytes = IOUtils.toByteArray(bis);
113         bis = new BufferedInputStream(publicInputStream);
114         byte[] publicBytes = IOUtils.toByteArray(bis);
115
116         KeyFactory keyFactory = KeyFactory.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
117         X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicBytes);
118         PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
119
120         PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateBytes);
121         PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
122
123         return new KeyPair(publicKey, privateKey);
124     }
125
126     @Test
127     void shouldReturnValidPkiMessageWhenCreateCertificateRequestMessageMethodCalledWithValidCsr()
128             throws Exception {
129         // given
130         Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
131         Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
132         setCsrModelAndServerValues(
133                 "mypassword",
134                 "senderKID",
135                 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
136                 beforeDate,
137                 afterDate);
138         when(httpClient.execute(any())).thenReturn(httpResponse);
139         when(httpResponse.getEntity()).thenReturn(httpEntity);
140
141         try (final InputStream is =
142                      this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile");
143              BufferedInputStream bis = new BufferedInputStream(is)) {
144
145             byte[] ba = IOUtils.toByteArray(bis);
146             doAnswer(
147                     invocation -> {
148                         OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
149                         os.write(ba);
150                         return null;
151                     })
152                     .when(httpEntity)
153                     .writeTo(any(OutputStream.class));
154         }
155         CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
156         // when
157         Cmpv2CertificationModel cmpClientResult =
158                 cmpClient.createCertificate(csrModel, server, notBefore, notAfter);
159         // then
160         assertNotNull(cmpClientResult);
161     }
162
163     @Test
164     void
165     shouldThrowCmpClientExceptionWhenCreateCertificateRequestMessageMethodCalledWithWrongProtectedBytesInResponse()
166             throws Exception {
167         // given
168         Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
169         Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
170         setCsrModelAndServerValues(
171                 "password",
172                 "senderKID",
173                 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
174                 beforeDate,
175                 afterDate);
176         when(httpClient.execute(any())).thenReturn(httpResponse);
177         when(httpResponse.getEntity()).thenReturn(httpEntity);
178
179         try (final InputStream is =
180                      this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile");
181              BufferedInputStream bis = new BufferedInputStream(is)) {
182
183             byte[] ba = IOUtils.toByteArray(bis);
184             doAnswer(
185                     invocation -> {
186                         OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
187                         os.write(ba);
188                         return null;
189                     })
190                     .when(httpEntity)
191                     .writeTo(any(OutputStream.class));
192         }
193         CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
194         // then
195         Assertions.assertThrows(
196                 CmpClientException.class,
197                 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
198     }
199
200     @Test
201     void shouldThrowCmpClientExceptionWithPkiErrorExceptionWhenCmpClientCalledWithBadPassword()
202             throws Exception {
203         // given
204         Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
205         Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
206         setCsrModelAndServerValues(
207                 "password",
208                 "senderKID",
209                 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
210                 beforeDate,
211                 afterDate);
212         when(httpClient.execute(any())).thenReturn(httpResponse);
213         when(httpResponse.getEntity()).thenReturn(httpEntity);
214
215         try (final InputStream is =
216                      this.getClass().getResourceAsStream("/ReturnedFailurePKIMessageBadPassword");
217              BufferedInputStream bis = new BufferedInputStream(is)) {
218
219             byte[] ba = IOUtils.toByteArray(bis);
220             doAnswer(
221                     invocation -> {
222                         OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
223                         os.write(ba);
224                         return null;
225                     })
226                     .when(httpEntity)
227                     .writeTo(any(OutputStream.class));
228         }
229         CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
230
231         // then
232         Assertions.assertThrows(
233                 CmpClientException.class,
234                 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
235     }
236
237     @Test
238     void shouldThrowIllegalArgumentExceptionWhencreateCertificateCalledWithInvalidCsr()
239             throws ParseException {
240         // given
241         Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
242         Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
243         setCsrModelAndServerValues(
244                 "password",
245                 "senderKID",
246                 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
247                 beforeDate,
248                 afterDate);
249         CmpClientImpl cmpClient = new CmpClientImpl(httpClient);
250         // then
251         Assertions.assertThrows(
252                 IllegalArgumentException.class,
253                 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
254     }
255
256     @Test
257     void shouldThrowIoExceptionWhenCreateCertificateCalledWithNoServerAvailable()
258             throws IOException, ParseException {
259         // given
260         Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
261         Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
262         setCsrModelAndServerValues(
263                 "myPassword",
264                 "sender",
265                 "http://127.0.0.1/ejbca/publicweb/cmp/cmpTest",
266                 beforeDate,
267                 afterDate);
268         when(httpClient.execute(any())).thenThrow(IOException.class);
269         CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
270         // then
271         Assertions.assertThrows(
272                 CmpClientException.class,
273                 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
274     }
275
276     private void setCsrModelAndServerValues(String iak, String rv, String externalCaUrl, Date notBefore, Date notAfter) {
277         csrModel = new CsrModel(null, dn, keyPair.getPrivate(), keyPair.getPublic(), new GeneralName[0]);
278
279         Authentication authentication = new Authentication();
280         authentication.setIak(iak);
281         authentication.setRv(rv);
282         server = new Cmpv2Server();
283         server.setAuthentication(authentication);
284         server.setUrl(externalCaUrl);
285         server.setIssuerDN(dn);
286         this.notBefore = notBefore;
287         this.notAfter = notAfter;
288     }
289 }