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.exceptions.CmpServerException;
66 import org.onap.oom.certservice.cmpv2client.impl.CmpClientImpl;
67 import org.onap.oom.certservice.cmpv2client.model.Cmpv2CertificationModel;
69 class Cmpv2ClientTest {
72 Security.addProvider(new BouncyCastleProvider());
75 private CsrModel csrModel;
76 private Cmpv2Server server;
77 private Date notBefore;
78 private Date notAfter;
85 CloseableHttpClient httpClient;
88 CloseableHttpResponse httpResponse;
91 HttpEntity httpEntity;
93 private static KeyPair keyPair;
97 throws NoSuchProviderException, NoSuchAlgorithmException, IOException,
98 InvalidKeySpecException {
99 keyPair = loadKeyPair();
100 dn = new X500NameBuilder()
101 .addRDN(BCStyle.O, "TestOrganization")
106 public KeyPair loadKeyPair()
107 throws IOException, NoSuchAlgorithmException, InvalidKeySpecException,
108 NoSuchProviderException {
110 final InputStream privateInputStream = this.getClass().getResourceAsStream("/privateKey");
111 final InputStream publicInputStream = this.getClass().getResourceAsStream("/publicKey");
112 BufferedInputStream bis = new BufferedInputStream(privateInputStream);
113 byte[] privateBytes = IOUtils.toByteArray(bis);
114 bis = new BufferedInputStream(publicInputStream);
115 byte[] publicBytes = IOUtils.toByteArray(bis);
117 KeyFactory keyFactory = KeyFactory.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
118 X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicBytes);
119 PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
121 PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateBytes);
122 PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
124 return new KeyPair(publicKey, privateKey);
128 void shouldReturnValidPkiMessageWhenCreateCertificateRequestMessageMethodCalledWithValidCsr()
131 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
132 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
133 setCsrModelAndServerValues(
136 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
139 when(httpClient.execute(any())).thenReturn(httpResponse);
140 when(httpResponse.getEntity()).thenReturn(httpEntity);
142 try (final InputStream is =
143 this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile");
144 BufferedInputStream bis = new BufferedInputStream(is)) {
146 byte[] ba = IOUtils.toByteArray(bis);
149 OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
154 .writeTo(any(OutputStream.class));
156 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
158 Cmpv2CertificationModel cmpClientResult =
159 cmpClient.createCertificate(csrModel, server, notBefore, notAfter);
161 assertNotNull(cmpClientResult);
166 shouldThrowCmpClientExceptionWhenCreateCertificateRequestMessageMethodCalledWithWrongProtectedBytesInResponse()
169 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
170 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
171 setCsrModelAndServerValues(
174 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
177 when(httpClient.execute(any())).thenReturn(httpResponse);
178 when(httpResponse.getEntity()).thenReturn(httpEntity);
180 try (final InputStream is =
181 this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile");
182 BufferedInputStream bis = new BufferedInputStream(is)) {
184 byte[] ba = IOUtils.toByteArray(bis);
187 OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
192 .writeTo(any(OutputStream.class));
194 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
196 Assertions.assertThrows(
197 CmpClientException.class,
198 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
202 void shouldThrowCmpClientExceptionWithPkiErrorExceptionWhenCmpClientCalledWithBadPassword()
205 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
206 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
207 setCsrModelAndServerValues(
210 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
213 when(httpClient.execute(any())).thenReturn(httpResponse);
214 when(httpResponse.getEntity()).thenReturn(httpEntity);
216 try (final InputStream is =
217 this.getClass().getResourceAsStream("/ReturnedFailurePKIMessageBadPassword");
218 BufferedInputStream bis = new BufferedInputStream(is)) {
220 byte[] ba = IOUtils.toByteArray(bis);
223 OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
228 .writeTo(any(OutputStream.class));
230 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
233 Assertions.assertThrows(
234 CmpServerException.class,
235 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
239 void shouldThrowIllegalArgumentExceptionWhencreateCertificateCalledWithInvalidCsr()
240 throws ParseException {
242 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
243 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
244 setCsrModelAndServerValues(
247 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
250 CmpClientImpl cmpClient = new CmpClientImpl(httpClient);
252 Assertions.assertThrows(
253 IllegalArgumentException.class,
254 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
258 void shouldThrowIoExceptionWhenCreateCertificateCalledWithNoServerAvailable()
259 throws IOException, ParseException {
261 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
262 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
263 setCsrModelAndServerValues(
266 "http://127.0.0.1/ejbca/publicweb/cmp/cmpTest",
269 when(httpClient.execute(any())).thenThrow(IOException.class);
270 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
272 Assertions.assertThrows(
273 CmpClientException.class,
274 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
277 private void setCsrModelAndServerValues(String iak, String rv, String externalCaUrl, Date notBefore, Date notAfter) {
278 csrModel = new CsrModel(null, dn, keyPair.getPrivate(), keyPair.getPublic(), new GeneralName[0]);
280 Authentication authentication = new Authentication();
281 authentication.setIak(iak);
282 authentication.setRv(rv);
283 server = new Cmpv2Server();
284 server.setAuthentication(authentication);
285 server.setUrl(externalCaUrl);
286 server.setIssuerDN(dn);
287 this.notBefore = notBefore;
288 this.notAfter = notAfter;