Fix 'Order of TOSCA.meta field is hardcoded'-bug
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / CsarValidationUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 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 package org.openecomp.sdc.be.components.impl;
21
22 import fj.data.Either;
23 import java.io.ByteArrayInputStream;
24 import java.io.IOException;
25 import java.io.StringReader;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Optional;
31 import java.util.Properties;
32 import java.util.regex.Pattern;
33 import java.util.stream.Collectors;
34 import org.apache.commons.lang3.tuple.ImmutablePair;
35 import org.openecomp.sdc.be.config.BeEcompErrorManager;
36 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
37 import org.openecomp.sdc.be.dao.api.ActionStatus;
38 import org.openecomp.sdc.be.impl.ComponentsUtils;
39 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
40 import org.openecomp.sdc.be.tosca.CsarUtils;
41 import org.openecomp.sdc.common.log.wrappers.Logger;
42 import org.openecomp.sdc.common.util.GeneralUtility;
43 import org.openecomp.sdc.exception.ResponseFormat;
44
45 public class CsarValidationUtils {
46
47     private static final Logger log = Logger.getLogger(CsarValidationUtils.class.getName());
48     private static final String TOSCA_META_FILE_VERSION = "TOSCA-Meta-File-Version";
49     private static final String CSAR_VERSION = "CSAR-Version";
50     private static final String CREATED_BY = "Created-By";
51     private static final String NEW_LINE_DELM = "\n";
52     private static final String TOSCA_METADATA = "TOSCA-Metadata";
53     private static final String TOSCA_FILE = "TOSCA.meta";
54     private static final String DEL_PATTERN = "([/\\\\]+)";
55     public static final String TOSCA_METADATA_PATH_PATTERN = TOSCA_METADATA +
56         // Artifact Group (i.e Deployment/Informational)
57         DEL_PATTERN + TOSCA_FILE;
58     public static final String TOSCA_META_ENTRY_DEFINITIONS = "Entry-Definitions";
59     private static final String[] TOSCA_METADATA_FIELDS = {TOSCA_META_FILE_VERSION, CSAR_VERSION, CREATED_BY, TOSCA_META_ENTRY_DEFINITIONS};
60     private static final String ARTIFACTS_METADATA_FILE = "HEAT.meta";
61     private static final String TOSCA_CSAR_EXTENSION = ".csar";
62     private static final String TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID = "TOSCA-Metadata/TOSCA.meta file is not in expected key-value form in csar, csar ID '%s'";
63     private static final String TOSCA_METADATA_TOSCA_META_FILE_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_WITH_ID = "TOSCA-Metadata/TOSCA.meta file not in expected key-value form in CSAR with id ";
64     private static final String CSAR_INTERNALS_ARE_INVALID = "CSAR internals are invalid";
65     private static final String ENTRY_DEFINITIONS_ENTRY_NOT_FOUND_IN_TOSCA_METADATA_TOSCA_META_FILE_CSAR_ID = "Entry-Definitions entry not found in TOSCA-Metadata/TOSCA.meta file, csar ID {}";
66     private static final String FILE_NOT_FOUND_IN_CSAR_WITH_ID = " file not found in CSAR with id ";
67     private static final String CSAR_STRUCTURE_IS_INVALID = "CSAR structure is invalid";
68     private static final String ENTRY_DEFINITIONS = "Entry-Definitions ";
69     private static final Pattern floatPattern = Pattern.compile("^\\d+\\.\\d+$");
70
71     /**
72      * Utility classes, which are collections of static members, are not meant to be instantiated
73      */
74     private CsarValidationUtils() {
75     }
76
77     /**
78      * Validates Csar
79      *
80      * @param csar
81      * @param csarUUID
82      * @param componentsUtils
83      * @return
84      */
85     public static Either<Boolean, ResponseFormat> validateCsar(Map<String, byte[]> csar, String csarUUID, ComponentsUtils componentsUtils) {
86         Either<Boolean, ResponseFormat> validateStatus = validateIsTOSCAMetadataExist(csar, csarUUID, componentsUtils);
87         if (validateStatus.isRight()) {
88             return validateStatus;
89         }
90         removeNonUniqueArtifactsFromCsar(csar);
91         log.trace("TOSCA-Metadata/TOSCA.meta file found, CSAR id {}", csarUUID);
92         validateStatus = validateTOSCAMetadataFile(csar, csarUUID, componentsUtils);
93         if (validateStatus.isRight()) {
94             return validateStatus;
95         }
96         return Either.left(true);
97     }
98
99     private static void removeNonUniqueArtifactsFromCsar(Map<String, byte[]> csar) {
100         List<String> nonUniqueArtifactsToRemove = new ArrayList<>();
101         String[] paths = csar.keySet().toArray(new String[csar.keySet().size()]);
102         int numberOfArtifacts = paths.length;
103         for (int i = 0; i < numberOfArtifacts; ++i) {
104             collectNonUniqueArtifact(paths, i, numberOfArtifacts, nonUniqueArtifactsToRemove);
105         }
106         nonUniqueArtifactsToRemove.stream().forEach(csar::remove);
107     }
108
109     private static void collectNonUniqueArtifact(String[] paths, int currInd, int numberOfArtifacts, List<String> nonUniqueArtifactsToRemove) {
110         String[] parsedPath = paths[currInd].split("/");
111         String[] otherParsedPath;
112         int artifactNameInd = parsedPath.length - 1;
113         for (int j = currInd + 1; j < numberOfArtifacts; ++j) {
114             otherParsedPath = paths[j].split("/");
115             if (parsedPath.length == otherParsedPath.length && parsedPath.length > 3 && isEqualArtifactNames(parsedPath, otherParsedPath)) {
116                 log.error(
117                     "Can't upload two artifact with the same name {}. The artifact with path {} will be handled, and the artifact with path {} will be ignored. ",
118                     parsedPath[artifactNameInd], paths[currInd], paths[j]);
119                 nonUniqueArtifactsToRemove.add(paths[j]);
120             }
121         }
122     }
123
124     private static boolean isEqualArtifactNames(String[] parsedPath, String[] otherParsedPath) {
125         boolean isEqualArtifactNames = false;
126         int artifactNameInd = parsedPath.length - 1;
127         int artifactGroupTypeInd = parsedPath.length - 3;
128         String groupType = parsedPath[artifactGroupTypeInd];
129         String artifactName = parsedPath[artifactNameInd];
130         String otherGroupType = otherParsedPath[artifactGroupTypeInd];
131         String otherArtifactName = otherParsedPath[artifactNameInd];
132         String vfcToscaName = parsedPath.length == 5 ? parsedPath[1] : null;
133         if (artifactName.equalsIgnoreCase(otherArtifactName) && groupType.equalsIgnoreCase(otherGroupType)) {
134             isEqualArtifactNames = vfcToscaName == null || vfcToscaName.equalsIgnoreCase(otherParsedPath[1]);
135         }
136         return isEqualArtifactNames;
137     }
138
139     public static Either<ImmutablePair<String, String>, ResponseFormat> getToscaYaml(Map<String, byte[]> csar, String csarUUID,
140                                                                                      ComponentsUtils componentsUtils, AuditingActionEnum auditingAction) {
141         if (!AuditingActionEnum.UPDATE_SERVICE_TOSCA_TEMPLATE.equals(auditingAction)) {
142             Either<Boolean, ResponseFormat> validateStatus = validateIsTOSCAMetadataExist(csar, csarUUID, componentsUtils);
143             if (validateStatus.isRight()) {
144                 return Either.right(validateStatus.right().value());
145             }
146         }
147         Pattern pattern = Pattern.compile(TOSCA_METADATA_PATH_PATTERN);
148         Optional<String> keyOp = csar.keySet().stream().filter(k -> pattern.matcher(k).matches()).findAny();
149         if (keyOp.isEmpty()) {
150             log.error(String.format(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID));
151             BeEcompErrorManager.getInstance()
152                 .logInternalDataError(TOSCA_METADATA_TOSCA_META_FILE_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_WITH_ID + csarUUID,
153                     CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR);
154             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID_FORMAT, csarUUID,
155                 String.format(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID)));
156         }
157         Properties props = new Properties();
158         try {
159             props.load(new StringReader(new String(csar.get(keyOp.get())).replace("\\", "\\\\")));
160         } catch (IOException e) {
161             log.error(String.format(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID), e);
162             BeEcompErrorManager.getInstance()
163                 .logInternalDataError(TOSCA_METADATA_TOSCA_META_FILE_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_WITH_ID + csarUUID,
164                     CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR);
165             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID_FORMAT, csarUUID,
166                 String.format(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID)));
167         }
168         String yamlFileName = props.getProperty(TOSCA_META_ENTRY_DEFINITIONS);
169         String result = Arrays.asList(yamlFileName.split(DEL_PATTERN)).stream().map(x -> x).collect(Collectors.joining(DEL_PATTERN));
170         keyOp = csar.keySet().stream().filter(k -> Pattern.compile(result).matcher(k).matches()).findAny();
171         if (keyOp.isEmpty()) {
172             log.error(ENTRY_DEFINITIONS_ENTRY_NOT_FOUND_IN_TOSCA_METADATA_TOSCA_META_FILE_CSAR_ID, csarUUID);
173             BeEcompErrorManager.getInstance()
174                 .logInternalDataError(ENTRY_DEFINITIONS_ENTRY_NOT_FOUND_IN_TOSCA_METADATA_TOSCA_META_FILE_CSAR_ID + csarUUID,
175                     CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR);
176             return Either.right(componentsUtils.getResponseFormat(ActionStatus.YAML_NOT_FOUND_IN_CSAR, csarUUID, yamlFileName));
177         }
178         log.trace("Found Entry-Definitions property in TOSCA-Metadata/TOSCA.meta, Entry-Definitions: {}, CSAR id: {}", yamlFileName, csarUUID);
179         byte[] yamlFileBytes = csar.get(yamlFileName);
180         if (yamlFileBytes == null) {
181             log.error("Entry-Definitions {} file not found in csar, csar ID {}", yamlFileName, csarUUID);
182             BeEcompErrorManager.getInstance()
183                 .logInternalDataError(ENTRY_DEFINITIONS + yamlFileName + FILE_NOT_FOUND_IN_CSAR_WITH_ID + csarUUID, CSAR_STRUCTURE_IS_INVALID,
184                     ErrorSeverity.ERROR);
185             return Either.right(componentsUtils.getResponseFormat(ActionStatus.YAML_NOT_FOUND_IN_CSAR, csarUUID, yamlFileName));
186         }
187         return Either.left(new ImmutablePair<>(yamlFileName, new String(yamlFileBytes)));
188     }
189
190     public static Either<ImmutablePair<String, String>, ResponseFormat> getArtifactsMeta(Map<String, byte[]> csar, String csarUUID,
191                                                                                          ComponentsUtils componentsUtils) {
192         if (!csar.containsKey(CsarUtils.ARTIFACTS_PATH + ARTIFACTS_METADATA_FILE)) {
193             log.error(ENTRY_DEFINITIONS_ENTRY_NOT_FOUND_IN_TOSCA_METADATA_TOSCA_META_FILE_CSAR_ID, csarUUID);
194             BeEcompErrorManager.getInstance()
195                 .logInternalDataError(ENTRY_DEFINITIONS_ENTRY_NOT_FOUND_IN_TOSCA_METADATA_TOSCA_META_FILE_CSAR_ID + csarUUID,
196                     CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR);
197             return Either.right(componentsUtils.getResponseFormat(ActionStatus.YAML_NOT_FOUND_IN_CSAR, csarUUID, ARTIFACTS_METADATA_FILE));
198         }
199         log.trace("Found Entry-Definitions property in TOSCA-Metadata/TOSCA.meta, Entry-Definitions: {}, CSAR id: {}", ARTIFACTS_METADATA_FILE,
200             csarUUID);
201         byte[] artifactsMetaBytes = csar.get(CsarUtils.ARTIFACTS_PATH + ARTIFACTS_METADATA_FILE);
202         if (artifactsMetaBytes == null) {
203             log.error("Entry-Definitions {}{} file not found in csar, csar ID {}", CsarUtils.ARTIFACTS_PATH, ARTIFACTS_METADATA_FILE, csarUUID);
204             BeEcompErrorManager.getInstance().logInternalDataError(
205                 ENTRY_DEFINITIONS + CsarUtils.ARTIFACTS_PATH + ARTIFACTS_METADATA_FILE + FILE_NOT_FOUND_IN_CSAR_WITH_ID + csarUUID,
206                 CSAR_STRUCTURE_IS_INVALID, ErrorSeverity.ERROR);
207             return Either.right(
208                 componentsUtils.getResponseFormat(ActionStatus.YAML_NOT_FOUND_IN_CSAR, csarUUID, CsarUtils.ARTIFACTS_PATH + ARTIFACTS_METADATA_FILE));
209         }
210         return Either.left(new ImmutablePair<>(CsarUtils.ARTIFACTS_PATH + ARTIFACTS_METADATA_FILE, new String(artifactsMetaBytes)));
211     }
212
213     public static Either<ImmutablePair<String, byte[]>, ResponseFormat> getArtifactContent(String csarUUID, Map<String, byte[]> csar,
214                                                                                            String artifactPath, String artifactName,
215                                                                                            ComponentsUtils componentsUtils) {
216         if (!csar.containsKey(artifactPath)) {
217             log.error("Entry-Definitions entry not found in Artifacts/HEAT.meta file, csar ID {}", csarUUID);
218             BeEcompErrorManager.getInstance()
219                 .logInternalDataError(ENTRY_DEFINITIONS_ENTRY_NOT_FOUND_IN_TOSCA_METADATA_TOSCA_META_FILE_CSAR_ID + csarUUID,
220                     CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR);
221             return Either
222                 .right(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_NOT_FOUND_IN_CSAR, CsarUtils.ARTIFACTS_PATH + artifactName, csarUUID));
223         }
224         log.trace("Found Entry-Definitions property in Artifacts/HEAT.meta, Entry-Definitions: {}, CSAR id: {}", artifactPath, csarUUID);
225         byte[] artifactFileBytes = csar.get(artifactPath);
226         if (artifactFileBytes == null) {
227             log.error("Entry-Definitions {}{} file not found in csar, csar ID {}", CsarUtils.ARTIFACTS_PATH, artifactName, csarUUID);
228             BeEcompErrorManager.getInstance()
229                 .logInternalDataError(ENTRY_DEFINITIONS + artifactPath + FILE_NOT_FOUND_IN_CSAR_WITH_ID + csarUUID, CSAR_STRUCTURE_IS_INVALID,
230                     ErrorSeverity.ERROR);
231             return Either.right(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_NOT_FOUND_IN_CSAR, artifactPath, csarUUID));
232         }
233         return Either.left(new ImmutablePair<>(artifactName, artifactFileBytes));
234     }
235
236     private static Either<Boolean, ResponseFormat> validateTOSCAMetadataFile(Map<String, byte[]> csar, String csarUUID,
237                                                                              ComponentsUtils componentsUtils) {
238         Pattern pattern = Pattern.compile(TOSCA_METADATA_PATH_PATTERN);
239         Optional<String> keyOp = csar.keySet().stream().filter(k -> pattern.matcher(k).matches()).findAny();
240         if (keyOp.isEmpty()) {
241             log.error(String.format(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID));
242             BeEcompErrorManager.getInstance()
243                 .logInternalDataError(TOSCA_METADATA_TOSCA_META_FILE_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_WITH_ID + csarUUID,
244                     CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR);
245             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID_FORMAT, csarUUID,
246                 String.format(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID)));
247         }
248         String toscaMetadata = new String(csar.get(keyOp.get()));
249         Either<Boolean, ResponseFormat> blockStatus = validateBlock(csarUUID, componentsUtils, toscaMetadata);
250         if (blockStatus.isRight()) {
251             return blockStatus;
252         }
253         return Either.left(true);
254     }
255
256     private static Either<Boolean, ResponseFormat> validateBlock(String csarUUID, ComponentsUtils componentsUtils, String toscaMetadata) {
257         final String[] splited = toscaMetadata.split(NEW_LINE_DELM);
258         if (splited == null || splited.length < TOSCA_METADATA_FIELDS.length) {
259             log.error(String.format(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID));
260             BeEcompErrorManager.getInstance()
261                 .logInternalDataError(TOSCA_METADATA_TOSCA_META_FILE_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_WITH_ID + csarUUID,
262                     CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR);
263             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID_FORMAT, csarUUID,
264                 String.format(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID)));
265         }
266         final Properties props = new Properties();
267         try {
268             props.load(new ByteArrayInputStream(toscaMetadata.getBytes()));
269         } catch (final IOException e) {
270             log.error(String.format(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID), e);
271             BeEcompErrorManager.getInstance()
272                 .logInternalDataError(TOSCA_METADATA_TOSCA_META_FILE_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_WITH_ID + csarUUID,
273                     CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR);
274             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID_FORMAT, csarUUID,
275                 String.format(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID)));
276         }
277         for (final String toscaField : TOSCA_METADATA_FIELDS) {
278             if (!props.containsKey(toscaField)) {
279                 final String msg = "TOSCA.meta file format is invalid: No new line after block_0 as expected in csar, csar ID {}";
280                 log.error(msg, csarUUID);
281                 BeEcompErrorManager.getInstance()
282                     .logInternalDataError(TOSCA_METADATA_TOSCA_META_FILE_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_WITH_ID + csarUUID,
283                         CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR);
284                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID_FORMAT, csarUUID, msg, csarUUID));
285             }
286             final String value = props.getProperty(toscaField);
287             if (value == null || value.isEmpty()) {
288                 log.error(String.format(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID));
289                 BeEcompErrorManager.getInstance()
290                     .logInternalDataError(TOSCA_METADATA_TOSCA_META_FILE_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_WITH_ID + csarUUID,
291                         CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR);
292                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID_FORMAT, csarUUID,
293                     String.format(TOSCA_METADATA_TOSCA_META_FILE_IS_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_CSAR_ID, csarUUID)));
294             }
295             // TOSCA-Meta-File-Version & CSAR-Version : digit.digit - format validation
296             if ((toscaField.equals(TOSCA_META_FILE_VERSION) || toscaField.equals(CSAR_VERSION)) && !validateTOSCAMetaProperty(value)) {
297                 final String msg = "TOSCA-Metadata/TOSCA.meta file contains {} in wrong format (digit.digit), csar ID {}";
298                 log.error(msg, toscaField, csarUUID);
299                 BeEcompErrorManager.getInstance()
300                     .logInternalDataError(TOSCA_METADATA_TOSCA_META_FILE_NOT_IN_EXPECTED_KEY_VALUE_FORM_IN_CSAR_WITH_ID + csarUUID,
301                         CSAR_INTERNALS_ARE_INVALID, ErrorSeverity.ERROR);
302                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID_FORMAT, csarUUID, msg, toscaField, csarUUID));
303             }
304         }
305         return Either.left(true);
306     }
307
308     private static boolean validateTOSCAMetaProperty(String toscaProperty) {
309         return floatPattern.matcher(toscaProperty).matches();
310     }
311
312     private static Either<Boolean, ResponseFormat> validateIsTOSCAMetadataExist(Map<String, byte[]> csar, String csarUUID,
313                                                                                 ComponentsUtils componentsUtils) {
314         if (csar == null || csar.isEmpty()) {
315             log.error("Error when fetching csar with ID {}", csarUUID);
316             BeEcompErrorManager.getInstance().logBeDaoSystemError("Creating resource from CSAR: fetching CSAR with id " + csarUUID + " failed");
317             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID, csarUUID));
318         }
319         Pattern pattern = Pattern.compile(TOSCA_METADATA_PATH_PATTERN);
320         Optional<String> keyOp = csar.keySet().stream().filter(k -> pattern.matcher(k).matches()).findAny();
321         if (keyOp.isEmpty()) {
322             log.error("TOSCA-Metadata/TOSCA.meta file not found in csar, csar ID {}", csarUUID);
323             BeEcompErrorManager.getInstance()
324                 .logInternalDataError("TOSCA-Metadata/TOSCA.meta file not found in CSAR with id " + csarUUID, CSAR_STRUCTURE_IS_INVALID,
325                     ErrorSeverity.ERROR);
326             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID, csarUUID));
327         }
328         byte[] toscaMetaBytes = csar.get(keyOp.get());
329         if (toscaMetaBytes == null || toscaMetaBytes.length == 0) {
330             log.error("TOSCA-Metadata/TOSCA.meta file not found in csar, csar ID {}", csarUUID);
331             BeEcompErrorManager.getInstance()
332                 .logInternalDataError("TOSCA-Metadata/TOSCA.meta file not found in CSAR with id " + csarUUID, CSAR_STRUCTURE_IS_INVALID,
333                     ErrorSeverity.ERROR);
334             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID, csarUUID));
335         }
336         return Either.left(Boolean.TRUE);
337     }
338
339     public static Either<String, ResponseFormat> getToscaYamlChecksum(Map<String, byte[]> csar, String csarUUID, ComponentsUtils componentsUtils) {
340         Either<ImmutablePair<String, String>, ResponseFormat> toscaYamlRes = getToscaYaml(csar, csarUUID, componentsUtils, AuditingActionEnum.GET_TOSCA_MODEL);
341         if (toscaYamlRes.isRight() || toscaYamlRes.left().value() == null || toscaYamlRes.left().value().getRight() == null) {
342             log.error("Faild to create toscaYamlChecksum for csar, csar ID {}", csarUUID);
343             return Either.right(toscaYamlRes.right().value());
344         }
345         return Either.left(GeneralUtility.calculateMD5Base64EncodedByByteArray(toscaYamlRes.left().value().getRight().getBytes()));
346     }
347
348     public static boolean isCsarPayloadName(String payloadName) {
349         return payloadName != null && payloadName.toLowerCase().endsWith(TOSCA_CSAR_EXTENSION);
350     }
351 }