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.aaf.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.jce.provider.BouncyCastleProvider;
56 import org.junit.jupiter.api.Assertions;
57 import org.junit.jupiter.api.BeforeEach;
58 import org.junit.jupiter.api.Test;
59 import org.mockito.Mock;
60 import org.onap.aaf.certservice.certification.configuration.model.Authentication;
61 import org.onap.aaf.certservice.certification.configuration.model.Cmpv2Server;
62 import org.onap.aaf.certservice.certification.model.CsrModel;
63 import org.onap.aaf.certservice.cmpv2client.exceptions.CmpClientException;
64 import org.onap.aaf.certservice.cmpv2client.impl.CmpClientImpl;
66 class Cmpv2ClientTest {
69 Security.addProvider(new BouncyCastleProvider());
72 private CsrModel csrModel;
73 private Cmpv2Server server;
74 private Date notBefore;
75 private Date notAfter;
82 CloseableHttpClient httpClient;
85 CloseableHttpResponse httpResponse;
88 HttpEntity httpEntity;
90 private static KeyPair keyPair;
94 throws NoSuchProviderException, NoSuchAlgorithmException, IOException,
95 InvalidKeySpecException {
96 keyPair = loadKeyPair();
97 dn = new X500NameBuilder()
98 .addRDN(BCStyle.O, "TestOrganization")
103 public KeyPair loadKeyPair()
104 throws IOException, NoSuchAlgorithmException, InvalidKeySpecException,
105 NoSuchProviderException {
107 final InputStream privateInputStream = this.getClass().getResourceAsStream("/privateKey");
108 final InputStream publicInputStream = this.getClass().getResourceAsStream("/publicKey");
109 BufferedInputStream bis = new BufferedInputStream(privateInputStream);
110 byte[] privateBytes = IOUtils.toByteArray(bis);
111 bis = new BufferedInputStream(publicInputStream);
112 byte[] publicBytes = IOUtils.toByteArray(bis);
114 KeyFactory keyFactory = KeyFactory.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
115 X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicBytes);
116 PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
118 PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateBytes);
119 PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
121 return new KeyPair(publicKey, privateKey);
125 void shouldReturnValidPkiMessageWhenCreateCertificateRequestMessageMethodCalledWithValidCsr()
128 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
129 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
130 setCsrModelAndServerValues(
133 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
136 when(httpClient.execute(any())).thenReturn(httpResponse);
137 when(httpResponse.getEntity()).thenReturn(httpEntity);
139 try (final InputStream is =
140 this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile");
141 BufferedInputStream bis = new BufferedInputStream(is)) {
143 byte[] ba = IOUtils.toByteArray(bis);
146 OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
151 .writeTo(any(OutputStream.class));
153 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
155 List<List<X509Certificate>> cmpClientResult =
156 cmpClient.createCertificate("data", "RA", csrModel, server, cert, notBefore, notAfter);
158 assertNotNull(cmpClientResult);
163 shouldThrowCmpClientExceptionWhenCreateCertificateRequestMessageMethodCalledWithWrongProtectedBytesInResponse()
166 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
167 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
168 setCsrModelAndServerValues(
171 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
174 when(httpClient.execute(any())).thenReturn(httpResponse);
175 when(httpResponse.getEntity()).thenReturn(httpEntity);
177 try (final InputStream is =
178 this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile");
179 BufferedInputStream bis = new BufferedInputStream(is)) {
181 byte[] ba = IOUtils.toByteArray(bis);
184 OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
189 .writeTo(any(OutputStream.class));
191 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
193 Assertions.assertThrows(
194 CmpClientException.class,
195 () -> cmpClient.createCertificate("data", "RA", csrModel, server, cert, notBefore, notAfter));
199 void shouldThrowCmpClientExceptionWithPkiErrorExceptionWhenCmpClientCalledWithBadPassword()
202 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
203 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
204 setCsrModelAndServerValues(
207 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
210 when(httpClient.execute(any())).thenReturn(httpResponse);
211 when(httpResponse.getEntity()).thenReturn(httpEntity);
213 try (final InputStream is =
214 this.getClass().getResourceAsStream("/ReturnedFailurePKIMessageBadPassword");
215 BufferedInputStream bis = new BufferedInputStream(is)) {
217 byte[] ba = IOUtils.toByteArray(bis);
220 OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
225 .writeTo(any(OutputStream.class));
227 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
230 Assertions.assertThrows(
231 CmpClientException.class,
232 () -> cmpClient.createCertificate("data", "RA", csrModel, server, cert, notBefore, notAfter));
236 void shouldThrowIllegalArgumentExceptionWhencreateCertificateCalledWithInvalidCsr()
237 throws ParseException {
239 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
240 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
241 setCsrModelAndServerValues(
244 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
247 CmpClientImpl cmpClient = new CmpClientImpl(httpClient);
249 Assertions.assertThrows(
250 IllegalArgumentException.class,
251 () -> cmpClient.createCertificate("data", "RA", csrModel, server, cert, notBefore, notAfter));
255 void shouldThrowIoExceptionWhenCreateCertificateCalledWithNoServerAvailable()
256 throws IOException, ParseException {
258 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
259 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
260 setCsrModelAndServerValues(
263 "http://127.0.0.1/ejbca/publicweb/cmp/cmpTest",
266 when(httpClient.execute(any())).thenThrow(IOException.class);
267 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
269 Assertions.assertThrows(
270 CmpClientException.class,
271 () -> cmpClient.createCertificate("data", "RA", csrModel, server, cert, notBefore, notAfter));
274 private void setCsrModelAndServerValues(String iak, String rv, String externalCaUrl, Date notBefore, Date notAfter) {
275 csrModel = new CsrModel(null, dn, keyPair.getPrivate(), keyPair.getPublic(), Collections.emptyList());
277 Authentication authentication = new Authentication();
278 authentication.setIak(iak);
279 authentication.setRv(rv);
280 server = new Cmpv2Server();
281 server.setAuthentication(authentication);
282 server.setUrl(externalCaUrl);
283 server.setIssuerDN(dn);
284 this.notBefore = notBefore;
285 this.notAfter = notAfter;