5f880701f3037562c4f7fff14807e08ce1948e38
[sdc.git] / openecomp-be / backend / openecomp-sdc-vendor-software-product-manager / src / test / java / org / openecomp / sdc / vendorsoftwareproduct / impl / orchestration / csar / validation / CsarSecurityValidatorTest.java
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019 Nordix Foundation
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        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.
15  *
16  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19
20 package org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation;
21
22 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
23 import static org.hamcrest.core.Is.is;
24 import static org.junit.Assert.assertThat;
25 import static org.junit.Assert.fail;
26 import static org.mockito.ArgumentMatchers.any;
27 import static org.mockito.ArgumentMatchers.anyBoolean;
28 import static org.mockito.ArgumentMatchers.anyInt;
29 import static org.mockito.ArgumentMatchers.anyString;
30 import static org.mockito.ArgumentMatchers.eq;
31 import static org.mockito.Mockito.when;
32 import static org.mockito.MockitoAnnotations.openMocks;
33 import static org.openecomp.sdc.be.csar.storage.StorageFactory.StorageType.MINIO;
34
35 import io.minio.GetObjectArgs;
36 import io.minio.GetObjectResponse;
37 import io.minio.MinioClient;
38 import java.io.BufferedInputStream;
39 import java.io.ByteArrayInputStream;
40 import java.io.IOException;
41 import java.net.URI;
42 import java.net.URISyntaxException;
43 import java.nio.file.Files;
44 import java.nio.file.Path;
45 import java.nio.file.Paths;
46 import java.util.HashMap;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.UUID;
50 import java.util.stream.Collectors;
51 import org.junit.jupiter.api.AfterEach;
52 import org.junit.jupiter.api.Assertions;
53 import org.junit.jupiter.api.BeforeEach;
54 import org.junit.jupiter.api.Test;
55 import org.junit.jupiter.api.extension.ExtendWith;
56 import org.mockito.Answers;
57 import org.mockito.Mock;
58 import org.mockito.MockedStatic;
59 import org.mockito.Mockito;
60 import org.mockito.junit.jupiter.MockitoExtension;
61 import org.openecomp.sdc.be.csar.storage.ArtifactInfo;
62 import org.openecomp.sdc.be.csar.storage.MinIoArtifactInfo;
63 import org.openecomp.sdc.common.CommonConfigurationManager;
64 import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.OnboardingPackageProcessor;
65 import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.validation.CnfPackageValidator;
66 import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManager;
67 import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManagerException;
68 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo;
69 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardSignedPackage;
70
71 @ExtendWith(MockitoExtension.class)
72 class CsarSecurityValidatorTest {
73
74     private static final String BASE_DIR = "/vspmanager.csar/signing/";
75     private static final String DELIMITER = "---";
76     private CsarSecurityValidator csarSecurityValidator;
77     @Mock
78     private SecurityManager securityManager;
79     @Mock
80     private CommonConfigurationManager commonConfigurationManager;
81     @Mock
82     private MinioClient minioClient;
83     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
84     private MinioClient.Builder builderMinio;
85     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
86     private GetObjectArgs.Builder getObjectArgsBuilder;
87     @Mock
88     private GetObjectArgs getObjectArgs;
89
90     @AfterEach
91     void tearDown() throws Exception {
92         restore();
93     }
94
95     private void restore() throws Exception {
96         final URI uri = CsarSecurityValidatorTest.class.getResource(BASE_DIR).toURI();
97         final List<Path> list = Files.list(Path.of(uri.getPath())).filter(path -> path.toString().contains(DELIMITER)).collect(Collectors.toList());
98         for (final Path path : list) {
99             final String[] split = path.toString().split(DELIMITER);
100             Files.move(path, Path.of(split[0]), REPLACE_EXISTING);
101         }
102     }
103
104     @BeforeEach
105     public void setUp() throws Exception {
106         openMocks(this);
107         csarSecurityValidator = new CsarSecurityValidator(securityManager);
108         backup();
109     }
110
111     private void backup() throws Exception {
112         final URI uri = CsarSecurityValidatorTest.class.getResource(BASE_DIR).toURI();
113         final List<Path> list = Files.list(Path.of(uri.getPath())).collect(Collectors.toList());
114         for (final Path path : list) {
115             Files.copy(path, Path.of(path.toString() + DELIMITER + UUID.randomUUID()), REPLACE_EXISTING);
116         }
117     }
118
119     @Test
120     void isSignatureValidTestCorrectStructureAndValidSignatureExists() throws SecurityManagerException {
121         final byte[] packageBytes = getFileBytesOrFail("signed-package.zip");
122         final OnboardPackageInfo onboardPackageInfo = loadSignedPackageWithArtifactInfoS3Store("signed-package.zip", packageBytes, null);
123         when(securityManager.verifyPackageSignedData(any(OnboardSignedPackage.class), any(ArtifactInfo.class))).thenReturn(true);
124         final boolean isSignatureValid = csarSecurityValidator
125             .verifyPackageSignature((OnboardSignedPackage) onboardPackageInfo.getOriginalOnboardPackage(), onboardPackageInfo.getArtifactInfo());
126         assertThat("Signature should be valid", isSignatureValid, is(true));
127     }
128
129     @Test
130     void isSignatureValidTestCorrectStructureAndNotValidSignatureExists() throws Exception {
131
132         final Map<String, Object> endpoint = new HashMap<>();
133         endpoint.put("host", "localhost");
134         endpoint.put("port", 9000);
135         final Map<String, Object> credentials = new HashMap<>();
136         credentials.put("accessKey", "login");
137         credentials.put("secretKey", "password");
138
139         try (MockedStatic<CommonConfigurationManager> utilities = Mockito.mockStatic(CommonConfigurationManager.class)) {
140             utilities.when(CommonConfigurationManager::getInstance).thenReturn(commonConfigurationManager);
141             try (MockedStatic<MinioClient> minioUtilities = Mockito.mockStatic(MinioClient.class)) {
142                 minioUtilities.when(MinioClient::builder).thenReturn(builderMinio);
143                 when(builderMinio
144                     .endpoint(anyString(), anyInt(), anyBoolean())
145                     .credentials(anyString(), anyString())
146                     .build()
147                 ).thenReturn(minioClient);
148
149                 when(commonConfigurationManager.getConfigValue("externalCsarStore", "endpoint", null)).thenReturn(endpoint);
150                 when(commonConfigurationManager.getConfigValue("externalCsarStore", "credentials", null)).thenReturn(credentials);
151                 when(commonConfigurationManager.getConfigValue("externalCsarStore", "tempPath", null)).thenReturn("cert/2-file-signed-package");
152                 when(commonConfigurationManager.getConfigValue(eq("externalCsarStore"), eq("storageType"), any())).thenReturn(MINIO.name());
153
154                 final byte[] packageBytes = getFileBytesOrFail("signed-package-tampered-data.zip");
155
156                 when(getObjectArgsBuilder
157                     .bucket(anyString())
158                     .object(anyString())
159                     .build()
160                 ).thenReturn(getObjectArgs);
161
162                 when(minioClient.getObject(any(GetObjectArgs.class)))
163                     .thenReturn(new GetObjectResponse(null, "bucket", "", "objectName",
164                         new BufferedInputStream(new ByteArrayInputStream(packageBytes))));
165
166                 final OnboardPackageInfo onboardPackageInfo = loadSignedPackageWithArtifactInfoS3Store("signed-package-tampered-data.zip",
167                     packageBytes,
168                     null);
169                 //no mocked securityManager
170                 csarSecurityValidator = new CsarSecurityValidator();
171                 Assertions.assertThrows(SecurityManagerException.class, () -> {
172                     csarSecurityValidator.verifyPackageSignature((OnboardSignedPackage) onboardPackageInfo.getOriginalOnboardPackage(),
173                         onboardPackageInfo.getArtifactInfo());
174                 });
175             }
176         }
177     }
178
179     @Test
180     void isSignatureValidTestCorrectStructureAndValidSignatureExistsArtifactStorageManagerIsEnabled() throws SecurityManagerException {
181         final byte[] packageBytes = getFileBytesOrFail("signed-package.zip");
182         final OnboardPackageInfo onboardPackageInfo = loadSignedPackageWithoutArtifactInfo("signed-package.zip",
183             packageBytes, null);
184         when(securityManager.verifySignedData(any(), any(), any())).thenReturn(true);
185         final boolean isSignatureValid = csarSecurityValidator
186             .verifyPackageSignature((OnboardSignedPackage) onboardPackageInfo.getOriginalOnboardPackage(), onboardPackageInfo.getArtifactInfo());
187
188         assertThat("Signature should be valid", isSignatureValid, is(true));
189     }
190
191     @Test
192     void isSignatureValidTestCorrectStructureAndNotValidSignatureExistsArtifactStorageManagerIsEnabled() throws SecurityManagerException {
193         final byte[] packageBytes = getFileBytesOrFail("signed-package-tampered-data.zip");
194         final OnboardPackageInfo onboardPackageInfo = loadSignedPackageWithoutArtifactInfo("signed-package-tampered-data.zip",
195             packageBytes, null);
196         //no mocked securityManager
197         csarSecurityValidator = new CsarSecurityValidator();
198         Assertions.assertThrows(SecurityManagerException.class, () -> {
199             csarSecurityValidator
200                 .verifyPackageSignature((OnboardSignedPackage) onboardPackageInfo.getOriginalOnboardPackage(), onboardPackageInfo.getArtifactInfo());
201         });
202     }
203
204     private byte[] getFileBytesOrFail(final String path) {
205         try {
206             return getFileBytes(path);
207         } catch (final URISyntaxException | IOException e) {
208             fail("Could not load file " + path);
209             return null;
210         }
211     }
212
213     private byte[] getFileBytes(final String path) throws URISyntaxException, IOException {
214         return Files.readAllBytes(Paths.get(
215             CsarSecurityValidatorTest.class.getResource(BASE_DIR + path).toURI()));
216     }
217
218     private OnboardPackageInfo loadSignedPackageWithArtifactInfoS3Store(final String packageName, final byte[] packageBytes,
219                                                                         final CnfPackageValidator cnfPackageValidator) {
220         final OnboardingPackageProcessor onboardingPackageProcessor =
221             new OnboardingPackageProcessor(packageName, packageBytes, cnfPackageValidator, new MinIoArtifactInfo("bucket", "object"));
222         final OnboardPackageInfo onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
223         if (onboardPackageInfo == null) {
224             fail("Unexpected error. Could not load original package");
225         }
226
227         return onboardPackageInfo;
228     }
229
230     private OnboardPackageInfo loadSignedPackageWithoutArtifactInfo(final String packageName, final byte[] packageBytes,
231                                                                     final CnfPackageValidator cnfPackageValidator) {
232         final OnboardingPackageProcessor onboardingPackageProcessor =
233             new OnboardingPackageProcessor(packageName, packageBytes, cnfPackageValidator, null);
234         final OnboardPackageInfo onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
235         if (onboardPackageInfo == null) {
236             fail("Unexpected error. Could not load original package");
237         }
238
239         return onboardPackageInfo;
240     }
241 }