Implement improved MinIo client
[sdc.git] / openecomp-be / backend / openecomp-sdc-vendor-software-product-manager / src / test / java / org / openecomp / sdc / vendorsoftwareproduct / security / SecurityManagerTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.vendorsoftwareproduct.security;
22
23 import static junit.framework.TestCase.assertEquals;
24 import static junit.framework.TestCase.assertTrue;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.ArgumentMatchers.anyBoolean;
27 import static org.mockito.ArgumentMatchers.anyInt;
28 import static org.mockito.ArgumentMatchers.anyString;
29 import static org.mockito.ArgumentMatchers.eq;
30 import static org.mockito.Mockito.when;
31 import static org.mockito.MockitoAnnotations.openMocks;
32 import static org.openecomp.sdc.be.csar.storage.StorageFactory.StorageType.MINIO;
33
34 import io.minio.GetObjectArgs;
35 import io.minio.GetObjectResponse;
36 import io.minio.MinioClient;
37 import java.io.BufferedInputStream;
38 import java.io.ByteArrayInputStream;
39 import java.io.File;
40 import java.io.IOException;
41 import java.net.URISyntaxException;
42 import java.nio.file.Files;
43 import java.nio.file.Paths;
44 import java.util.HashMap;
45 import java.util.Map;
46 import org.apache.commons.io.FileUtils;
47 import org.junit.jupiter.api.AfterEach;
48 import org.junit.jupiter.api.Assertions;
49 import org.junit.jupiter.api.BeforeEach;
50 import org.junit.jupiter.api.Test;
51 import org.junit.jupiter.api.extension.ExtendWith;
52 import org.mockito.Answers;
53 import org.mockito.Mock;
54 import org.mockito.MockedStatic;
55 import org.mockito.Mockito;
56 import org.mockito.junit.jupiter.MockitoExtension;
57 import org.openecomp.sdc.be.csar.storage.MinIoArtifactInfo;
58 import org.openecomp.sdc.common.CommonConfigurationManager;
59 import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.OnboardingPackageProcessor;
60 import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.validation.CnfPackageValidator;
61 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo;
62 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardSignedPackage;
63
64 @ExtendWith(MockitoExtension.class)
65 class SecurityManagerTest {
66
67     private File certDir;
68     private String cerDirPath = "/tmp/cert/";
69     private SecurityManager securityManager;
70     @Mock
71     private CommonConfigurationManager commonConfigurationManager;
72     @Mock
73     private MinioClient minioClient;
74     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
75     private MinioClient.Builder builderMinio;
76     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
77     private GetObjectArgs.Builder getObjectArgsBuilder;
78     @Mock
79     private GetObjectArgs getObjectArgs;
80
81     private File prepareCertFiles(String origFilePath, String newFilePath) throws IOException, URISyntaxException {
82         File origFile = new File(getClass().getResource(origFilePath).toURI());
83         File newFile = new File(newFilePath);
84         newFile.createNewFile();
85         FileUtils.copyFile(origFile, newFile);
86         return newFile;
87     }
88
89     private byte[] readAllBytes(String path) throws URISyntaxException, IOException {
90         return Files.readAllBytes(Paths.get(getClass().getResource(path).toURI()));
91     }
92
93     @BeforeEach
94     public void setUp() throws IOException {
95         openMocks(this);
96         certDir = new File(cerDirPath);
97         if (certDir.exists()) {
98             tearDown();
99         }
100         certDir.mkdirs();
101         securityManager = new SecurityManager(certDir.getPath());
102
103     }
104
105     @AfterEach
106     public void tearDown() throws IOException {
107         if (certDir.exists()) {
108             FileUtils.deleteDirectory(certDir);
109         }
110         securityManager.cleanTrustedCertificates();
111     }
112
113     @Test
114     void testGetCertificates() throws IOException, SecurityManagerException, URISyntaxException {
115         File newFile = prepareCertFiles("/cert/root-certificate.pem", cerDirPath + "/root-certificate.pem");
116         assertEquals(1, securityManager.getTrustedCertificates().size());
117         newFile.delete();
118         assertEquals(0, securityManager.getTrustedCertificates().size());
119     }
120
121     @Test
122     void testGetCertificatesNoDirectory() throws IOException, SecurityManagerException {
123         certDir.delete();
124         assertEquals(0, securityManager.getTrustedCertificates().size());
125     }
126
127     @Test
128     void testGetCertificatesException() throws IOException, SecurityManagerException {
129         File newFile = new File(cerDirPath + "root-certificate.pem");
130         newFile.createNewFile();
131         Assertions.assertThrows(SecurityManagerException.class, () -> {
132             assertEquals(1, securityManager.getTrustedCertificates().size());
133         });
134         newFile.delete();
135         assertEquals(0, securityManager.getTrustedCertificates().size());
136
137     }
138
139     @Test
140     void testGetCertificatesUpdated() throws IOException, SecurityManagerException, URISyntaxException {
141         File newFile = prepareCertFiles("/cert/root-certificate.pem", cerDirPath + "root-certificate.pem");
142         assertEquals(1, securityManager.getTrustedCertificates().size());
143         File otherNewFile = prepareCertFiles("/cert/package-certificate.pem", cerDirPath + "package-certificate.pem");
144         assertEquals(2, securityManager.getTrustedCertificates().size());
145         otherNewFile.delete();
146         assertEquals(1, securityManager.getTrustedCertificates().size());
147         newFile.delete();
148         assertEquals(0, securityManager.getTrustedCertificates().size());
149     }
150
151     @Test
152     void verifySignedDataTestCertIncludedIntoSignature() throws IOException, URISyntaxException, SecurityManagerException {
153         prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
154         byte[] signature = readAllBytes("/cert/2-file-signed-package/dummyPnfv4.cms");
155         byte[] archive = readAllBytes("/cert/2-file-signed-package/dummyPnfv4.csar");
156         assertTrue(securityManager.verifySignedData(signature, null, archive));
157     }
158
159     @Test
160     void verifySignedDataTestCertIncludedIntoSignatureArtifactStorageManagerIsEnabled() throws Exception {
161
162         final Map<String, Object> endpoint = new HashMap<>();
163         endpoint.put("host", "localhost");
164         endpoint.put("port", 9000);
165         final Map<String, Object> credentials = new HashMap<>();
166         credentials.put("accessKey", "login");
167         credentials.put("secretKey", "password");
168
169         try (MockedStatic<CommonConfigurationManager> utilities = Mockito.mockStatic(CommonConfigurationManager.class)) {
170             utilities.when(CommonConfigurationManager::getInstance).thenReturn(commonConfigurationManager);
171             try (MockedStatic<MinioClient> minioUtilities = Mockito.mockStatic(MinioClient.class)) {
172                 minioUtilities.when(MinioClient::builder).thenReturn(builderMinio);
173                 when(builderMinio
174                     .endpoint(anyString(), anyInt(), anyBoolean())
175                     .credentials(anyString(), anyString())
176                     .build()
177                 ).thenReturn(minioClient);
178
179                 when(commonConfigurationManager.getConfigValue("externalCsarStore", "endpoint", null)).thenReturn(endpoint);
180                 when(commonConfigurationManager.getConfigValue("externalCsarStore", "credentials", null)).thenReturn(credentials);
181                 when(commonConfigurationManager.getConfigValue("externalCsarStore", "tempPath", null)).thenReturn("cert/2-file-signed-package");
182                 when(commonConfigurationManager.getConfigValue(eq("externalCsarStore"), eq("storageType"), any())).thenReturn(MINIO.name());
183                 when(commonConfigurationManager.getConfigValue(eq("externalCsarStore"), eq("uploadPartSize"), any())).thenReturn(50_000_000);
184
185                 prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
186                 byte[] fileToUploadBytes = readAllBytes("/cert/2-file-signed-package/2-file-signed-package.zip");
187                 when(getObjectArgsBuilder
188                     .bucket(anyString())
189                     .object(anyString())
190                     .build()
191                 ).thenReturn(getObjectArgs);
192
193                 when(minioClient.getObject(any(GetObjectArgs.class)))
194                     .thenReturn(new GetObjectResponse(null, "bucket", "", "objectName",
195                         new BufferedInputStream(new ByteArrayInputStream(fileToUploadBytes))));
196
197                 final var onboardingPackageProcessor = new OnboardingPackageProcessor("2-file-signed-package.zip", fileToUploadBytes,
198                     new CnfPackageValidator(), new MinIoArtifactInfo("bucket", "objectName"));
199                 final OnboardPackageInfo onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
200
201                 assertTrue(securityManager
202                     .verifyPackageSignedData((OnboardSignedPackage) onboardPackageInfo.getOriginalOnboardPackage(),
203                         onboardPackageInfo.getArtifactInfo()));
204             }
205         }
206     }
207
208     @Test
209     void verifySignedDataTestCertNotIncludedIntoSignatureButExpected() throws IOException, URISyntaxException, SecurityManagerException {
210         Assertions.assertThrows(SecurityManagerException.class, () -> {
211             prepareCertFiles("/cert/root.cert", cerDirPath + "root.cert");
212             byte[] signature = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cms");
213             byte[] archive = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.csar");
214             securityManager.verifySignedData(signature, null, archive);
215         });
216
217     }
218
219     @Test
220     void verifySignedDataTestCertNotIncludedIntoSignature() throws IOException, URISyntaxException, SecurityManagerException {
221         prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
222         byte[] signature = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cms");
223         byte[] archive = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.csar");
224         byte[] cert = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cert");
225         assertTrue(securityManager.verifySignedData(signature, cert, archive));
226     }
227
228     @Test
229     void verifySignedDataTestCertNotIncludedIntoSignatureArtifactStorageManagerIsEnabled() throws Exception {
230
231         final Map<String, Object> endpoint = new HashMap<>();
232         endpoint.put("host", "localhost");
233         endpoint.put("port", 9000);
234         final Map<String, Object> credentials = new HashMap<>();
235         credentials.put("accessKey", "login");
236         credentials.put("secretKey", "password");
237
238         try (MockedStatic<CommonConfigurationManager> utilities = Mockito.mockStatic(CommonConfigurationManager.class)) {
239             utilities.when(CommonConfigurationManager::getInstance).thenReturn(commonConfigurationManager);
240             try (MockedStatic<MinioClient> minioUtilities = Mockito.mockStatic(MinioClient.class)) {
241                 minioUtilities.when(MinioClient::builder).thenReturn(builderMinio);
242                 when(builderMinio
243                     .endpoint(anyString(), anyInt(), anyBoolean())
244                     .credentials(anyString(), anyString())
245                     .build()
246                 ).thenReturn(minioClient);
247
248                 when(commonConfigurationManager.getConfigValue("externalCsarStore", "endpoint", null)).thenReturn(endpoint);
249                 when(commonConfigurationManager.getConfigValue("externalCsarStore", "credentials", null)).thenReturn(credentials);
250                 when(commonConfigurationManager.getConfigValue("externalCsarStore", "tempPath", null)).thenReturn("tempPath");
251                 when(commonConfigurationManager.getConfigValue(eq("externalCsarStore"), eq("storageType"), any())).thenReturn(MINIO.name());
252                 when(commonConfigurationManager.getConfigValue(eq("externalCsarStore"), eq("uploadPartSize"), any())).thenReturn(50_000_000);
253
254                 prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
255                 byte[] fileToUploadBytes = readAllBytes("/cert/3-file-signed-package/3-file-signed-package.zip");
256                 when(getObjectArgsBuilder
257                     .bucket(anyString())
258                     .object(anyString())
259                     .build()
260                 ).thenReturn(getObjectArgs);
261
262                 when(minioClient.getObject(any(GetObjectArgs.class)))
263                     .thenReturn(new GetObjectResponse(null, "bucket", "", "objectName",
264                         new BufferedInputStream(new ByteArrayInputStream(fileToUploadBytes))));
265
266                 final var onboardingPackageProcessor = new OnboardingPackageProcessor("3-file-signed-package.zip", fileToUploadBytes,
267                     new CnfPackageValidator(), new MinIoArtifactInfo("bucket", "objectName"));
268                 final OnboardPackageInfo onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
269
270                 assertTrue(securityManager
271                     .verifyPackageSignedData((OnboardSignedPackage) onboardPackageInfo.getOriginalOnboardPackage(),
272                         onboardPackageInfo.getArtifactInfo()));
273             }
274         }
275     }
276
277     @Test
278     void verifySignedDataTestCertIntermediateNotIncludedIntoSignature() throws IOException, URISyntaxException, SecurityManagerException {
279         prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
280         prepareCertFiles("/cert/package2.cert", cerDirPath + "signing-ca2.crt");
281         byte[] signature = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cms");
282         byte[] archive = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.csar");
283         byte[] cert = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cert");
284         assertTrue(securityManager.verifySignedData(signature, cert, archive));
285     }
286
287     @Test
288     void verifySignedDataTestCertWrongIntermediate() throws IOException, URISyntaxException, SecurityManagerException {
289         Assertions.assertThrows(SecurityManagerException.class, () -> {
290             prepareCertFiles("/cert/root.cert", cerDirPath + "root.cert");
291             prepareCertFiles("/cert/signing-ca1.crt", cerDirPath + "signing-ca1.crt");
292             byte[] signature = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cms");
293             byte[] archive = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.csar");
294             byte[] cert = readAllBytes("/cert/3-file-signed-package/dummyPnfv4-no-intermediate.cert");
295             securityManager.verifySignedData(signature, cert, archive);
296         });
297
298     }
299
300     @Test
301     void verifySignedDataTestCertIncludedIntoSignatureWithWrongIntermediateInDirectory()
302         throws IOException, URISyntaxException, SecurityManagerException {
303         prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
304         prepareCertFiles("/cert/signing-ca1.crt", cerDirPath + "signing-ca1.crt");
305         byte[] signature = readAllBytes("/cert/2-file-signed-package/dummyPnfv4.cms");
306         byte[] archive = readAllBytes("/cert/2-file-signed-package/dummyPnfv4.csar");
307         assertTrue(securityManager.verifySignedData(signature, null, archive));
308     }
309
310     @Test
311     void verifySignedDataTestCertWrongIntermediateInDirectory() throws IOException, URISyntaxException, SecurityManagerException {
312         prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
313         prepareCertFiles("/cert/signing-ca1.crt", cerDirPath + "signing-ca1.crt");
314         byte[] signature = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cms");
315         byte[] archive = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.csar");
316         byte[] cert = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cert");
317         assertTrue(securityManager.verifySignedData(signature, cert, archive));
318     }
319
320     @Test
321     void verifySignedDataTestWrongCertificate() throws IOException, URISyntaxException, SecurityManagerException {
322         Assertions.assertThrows(SecurityManagerException.class, () -> {
323             prepareCertFiles("/cert/root-certificate.pem", cerDirPath + "root-certificate.cert");
324             byte[] signature = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cms");
325             byte[] archive = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.csar");
326             byte[] cert = readAllBytes("/cert/3-file-signed-package/dummyPnfv4.cert");
327             securityManager.verifySignedData(signature, cert, archive);
328         });
329
330     }
331
332     @Test
333     void verifySignedDataTestChangedArchive() throws IOException, URISyntaxException, SecurityManagerException {
334         Assertions.assertThrows(SecurityManagerException.class, () -> {
335             prepareCertFiles("/cert/root.cert", cerDirPath + "root.cert");
336             byte[] signature = readAllBytes("/cert/tampered-signed-package/dummyPnfv4.cms");
337             byte[] archive = readAllBytes("/cert/tampered-signed-package/dummyPnfv4.csar");
338             securityManager.verifySignedData(signature, null, archive);
339         });
340
341     }
342 }