2 * Copyright (C) 2019 Ericsson Software Technology AB. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 package org.onap.oom.certservice.cmpv2client;
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;
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;
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;
68 class Cmpv2ClientTest {
71 Security.addProvider(new BouncyCastleProvider());
74 private CsrModel csrModel;
75 private Cmpv2Server server;
76 private Date notBefore;
77 private Date notAfter;
84 CloseableHttpClient httpClient;
87 CloseableHttpResponse httpResponse;
90 HttpEntity httpEntity;
92 private static KeyPair keyPair;
96 throws NoSuchProviderException, NoSuchAlgorithmException, IOException,
97 InvalidKeySpecException {
98 keyPair = loadKeyPair();
99 dn = new X500NameBuilder()
100 .addRDN(BCStyle.O, "TestOrganization")
105 public KeyPair loadKeyPair()
106 throws IOException, NoSuchAlgorithmException, InvalidKeySpecException,
107 NoSuchProviderException {
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);
116 KeyFactory keyFactory = KeyFactory.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
117 X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicBytes);
118 PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
120 PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateBytes);
121 PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
123 return new KeyPair(publicKey, privateKey);
127 void shouldReturnValidPkiMessageWhenCreateCertificateRequestMessageMethodCalledWithValidCsr()
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(
135 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
138 when(httpClient.execute(any())).thenReturn(httpResponse);
139 when(httpResponse.getEntity()).thenReturn(httpEntity);
141 try (final InputStream is =
142 this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile");
143 BufferedInputStream bis = new BufferedInputStream(is)) {
145 byte[] ba = IOUtils.toByteArray(bis);
148 OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
153 .writeTo(any(OutputStream.class));
155 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
157 Cmpv2CertificationModel cmpClientResult =
158 cmpClient.createCertificate(csrModel, server, notBefore, notAfter);
160 assertNotNull(cmpClientResult);
165 shouldThrowCmpClientExceptionWhenCreateCertificateRequestMessageMethodCalledWithWrongProtectedBytesInResponse()
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(
173 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
176 when(httpClient.execute(any())).thenReturn(httpResponse);
177 when(httpResponse.getEntity()).thenReturn(httpEntity);
179 try (final InputStream is =
180 this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile");
181 BufferedInputStream bis = new BufferedInputStream(is)) {
183 byte[] ba = IOUtils.toByteArray(bis);
186 OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
191 .writeTo(any(OutputStream.class));
193 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
195 Assertions.assertThrows(
196 CmpClientException.class,
197 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
201 void shouldThrowCmpClientExceptionWithPkiErrorExceptionWhenCmpClientCalledWithBadPassword()
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(
209 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
212 when(httpClient.execute(any())).thenReturn(httpResponse);
213 when(httpResponse.getEntity()).thenReturn(httpEntity);
215 try (final InputStream is =
216 this.getClass().getResourceAsStream("/ReturnedFailurePKIMessageBadPassword");
217 BufferedInputStream bis = new BufferedInputStream(is)) {
219 byte[] ba = IOUtils.toByteArray(bis);
222 OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
227 .writeTo(any(OutputStream.class));
229 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
232 Assertions.assertThrows(
233 CmpClientException.class,
234 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
238 void shouldThrowIllegalArgumentExceptionWhencreateCertificateCalledWithInvalidCsr()
239 throws ParseException {
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(
246 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
249 CmpClientImpl cmpClient = new CmpClientImpl(httpClient);
251 Assertions.assertThrows(
252 IllegalArgumentException.class,
253 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
257 void shouldThrowIoExceptionWhenCreateCertificateCalledWithNoServerAvailable()
258 throws IOException, ParseException {
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(
265 "http://127.0.0.1/ejbca/publicweb/cmp/cmpTest",
268 when(httpClient.execute(any())).thenThrow(IOException.class);
269 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
271 Assertions.assertThrows(
272 CmpClientException.class,
273 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
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]);
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;