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;
65 import org.onap.aaf.certservice.cmpv2client.model.Cmpv2CertificationModel;
67 class Cmpv2ClientTest {
70 Security.addProvider(new BouncyCastleProvider());
73 private CsrModel csrModel;
74 private Cmpv2Server server;
75 private Date notBefore;
76 private Date notAfter;
83 CloseableHttpClient httpClient;
86 CloseableHttpResponse httpResponse;
89 HttpEntity httpEntity;
91 private static KeyPair keyPair;
95 throws NoSuchProviderException, NoSuchAlgorithmException, IOException,
96 InvalidKeySpecException {
97 keyPair = loadKeyPair();
98 dn = new X500NameBuilder()
99 .addRDN(BCStyle.O, "TestOrganization")
104 public KeyPair loadKeyPair()
105 throws IOException, NoSuchAlgorithmException, InvalidKeySpecException,
106 NoSuchProviderException {
108 final InputStream privateInputStream = this.getClass().getResourceAsStream("/privateKey");
109 final InputStream publicInputStream = this.getClass().getResourceAsStream("/publicKey");
110 BufferedInputStream bis = new BufferedInputStream(privateInputStream);
111 byte[] privateBytes = IOUtils.toByteArray(bis);
112 bis = new BufferedInputStream(publicInputStream);
113 byte[] publicBytes = IOUtils.toByteArray(bis);
115 KeyFactory keyFactory = KeyFactory.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
116 X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicBytes);
117 PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
119 PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateBytes);
120 PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
122 return new KeyPair(publicKey, privateKey);
126 void shouldReturnValidPkiMessageWhenCreateCertificateRequestMessageMethodCalledWithValidCsr()
129 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
130 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
131 setCsrModelAndServerValues(
134 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
137 when(httpClient.execute(any())).thenReturn(httpResponse);
138 when(httpResponse.getEntity()).thenReturn(httpEntity);
140 try (final InputStream is =
141 this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile");
142 BufferedInputStream bis = new BufferedInputStream(is)) {
144 byte[] ba = IOUtils.toByteArray(bis);
147 OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
152 .writeTo(any(OutputStream.class));
154 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
156 Cmpv2CertificationModel cmpClientResult =
157 cmpClient.createCertificate(csrModel, server, notBefore, notAfter);
159 assertNotNull(cmpClientResult);
164 shouldThrowCmpClientExceptionWhenCreateCertificateRequestMessageMethodCalledWithWrongProtectedBytesInResponse()
167 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
168 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
169 setCsrModelAndServerValues(
172 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
175 when(httpClient.execute(any())).thenReturn(httpResponse);
176 when(httpResponse.getEntity()).thenReturn(httpEntity);
178 try (final InputStream is =
179 this.getClass().getResourceAsStream("/ReturnedSuccessPKIMessageWithCertificateFile");
180 BufferedInputStream bis = new BufferedInputStream(is)) {
182 byte[] ba = IOUtils.toByteArray(bis);
185 OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
190 .writeTo(any(OutputStream.class));
192 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
194 Assertions.assertThrows(
195 CmpClientException.class,
196 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
200 void shouldThrowCmpClientExceptionWithPkiErrorExceptionWhenCmpClientCalledWithBadPassword()
203 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
204 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
205 setCsrModelAndServerValues(
208 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
211 when(httpClient.execute(any())).thenReturn(httpResponse);
212 when(httpResponse.getEntity()).thenReturn(httpEntity);
214 try (final InputStream is =
215 this.getClass().getResourceAsStream("/ReturnedFailurePKIMessageBadPassword");
216 BufferedInputStream bis = new BufferedInputStream(is)) {
218 byte[] ba = IOUtils.toByteArray(bis);
221 OutputStream os = (ByteArrayOutputStream) invocation.getArguments()[0];
226 .writeTo(any(OutputStream.class));
228 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
231 Assertions.assertThrows(
232 CmpClientException.class,
233 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
237 void shouldThrowIllegalArgumentExceptionWhencreateCertificateCalledWithInvalidCsr()
238 throws ParseException {
240 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
241 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
242 setCsrModelAndServerValues(
245 "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
248 CmpClientImpl cmpClient = new CmpClientImpl(httpClient);
250 Assertions.assertThrows(
251 IllegalArgumentException.class,
252 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
256 void shouldThrowIoExceptionWhenCreateCertificateCalledWithNoServerAvailable()
257 throws IOException, ParseException {
259 Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
260 Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
261 setCsrModelAndServerValues(
264 "http://127.0.0.1/ejbca/publicweb/cmp/cmpTest",
267 when(httpClient.execute(any())).thenThrow(IOException.class);
268 CmpClientImpl cmpClient = spy(new CmpClientImpl(httpClient));
270 Assertions.assertThrows(
271 CmpClientException.class,
272 () -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
275 private void setCsrModelAndServerValues(String iak, String rv, String externalCaUrl, Date notBefore, Date notAfter) {
276 csrModel = new CsrModel(null, dn, keyPair.getPrivate(), keyPair.getPublic(), Collections.emptyList());
278 Authentication authentication = new Authentication();
279 authentication.setIak(iak);
280 authentication.setRv(rv);
281 server = new Cmpv2Server();
282 server.setAuthentication(authentication);
283 server.setUrl(externalCaUrl);
284 server.setIssuerDN(dn);
285 this.notBefore = notBefore;
286 this.notAfter = notAfter;