Add support for simple yaml profile 1.2
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / AbstractValidationsServlet.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  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22
23 package org.openecomp.sdc.be.servlets;
24
25 import com.fasterxml.jackson.databind.ObjectMapper;
26 import com.google.gson.Gson;
27 import com.google.gson.JsonSyntaxException;
28 import fj.data.Either;
29 import java.util.Optional;
30 import org.apache.commons.codec.binary.Base64;
31 import org.apache.commons.collections4.MapUtils;
32 import org.apache.commons.io.IOUtils;
33 import org.apache.commons.lang3.StringUtils;
34 import org.apache.commons.lang3.tuple.ImmutablePair;
35 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
36 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
37 import org.openecomp.sdc.be.components.impl.ImportUtils;
38 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
39 import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
40 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
41 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
42 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
43 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
44 import org.openecomp.sdc.be.config.BeEcompErrorManager;
45 import org.openecomp.sdc.be.config.ConfigurationManager;
46 import org.openecomp.sdc.be.dao.api.ActionStatus;
47 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
48 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
49 import org.openecomp.sdc.be.impl.ComponentsUtils;
50 import org.openecomp.sdc.be.impl.ServletUtils;
51 import org.openecomp.sdc.be.model.ArtifactDefinition;
52 import org.openecomp.sdc.be.model.Resource;
53 import org.openecomp.sdc.be.model.UploadResourceInfo;
54 import org.openecomp.sdc.be.model.User;
55 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
56 import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
57 import org.openecomp.sdc.be.user.Role;
58 import org.openecomp.sdc.be.user.UserBusinessLogic;
59 import org.openecomp.sdc.be.utils.TypeUtils;
60 import org.openecomp.sdc.common.api.Constants;
61 import org.openecomp.sdc.common.api.UploadArtifactInfo;
62 import org.openecomp.sdc.common.datastructure.Wrapper;
63 import org.openecomp.sdc.common.log.wrappers.Logger;
64 import org.openecomp.sdc.common.util.GeneralUtility;
65 import org.openecomp.sdc.common.util.YamlToObjectConverter;
66 import org.openecomp.sdc.common.zip.ZipUtils;
67 import org.openecomp.sdc.common.zip.exception.ZipException;
68 import org.openecomp.sdc.exception.ResponseFormat;
69 import org.yaml.snakeyaml.Yaml;
70
71 import javax.servlet.ServletContext;
72 import javax.servlet.http.HttpServletRequest;
73 import javax.ws.rs.core.Response;
74 import java.io.File;
75 import java.io.FileInputStream;
76 import java.io.IOException;
77 import java.io.InputStream;
78 import java.lang.reflect.Type;
79 import java.nio.charset.StandardCharsets;
80 import java.util.Arrays;
81 import java.util.HashMap;
82 import java.util.List;
83 import java.util.Map;
84 import java.util.function.Supplier;
85
86 public abstract class AbstractValidationsServlet extends BeGenericServlet {
87
88     private static final Logger log = Logger.getLogger(AbstractValidationsServlet.class);
89     private static final String TOSCA_SIMPLE_YAML_PREFIX = "tosca_simple_yaml_";
90     private static final List<String> TOSCA_DEFINITION_VERSIONS = Arrays.asList(
91         TOSCA_SIMPLE_YAML_PREFIX + "1_0_0",
92         TOSCA_SIMPLE_YAML_PREFIX + "1_1_0",
93         "tosca_simple_profile_for_nfv_1_0_0",
94         TOSCA_SIMPLE_YAML_PREFIX + "1_0",
95         TOSCA_SIMPLE_YAML_PREFIX + "1_1",
96         TOSCA_SIMPLE_YAML_PREFIX + "1_2");
97     private static final List<String> TOSCA_YML_CSAR_VALID_SUFFIX = Arrays.asList(".yml", ".yaml", ".csar");
98
99     protected ServletUtils servletUtils;
100     protected ResourceImportManager resourceImportManager;
101     protected final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
102
103
104     public AbstractValidationsServlet(UserBusinessLogic userBusinessLogic,
105         ComponentInstanceBusinessLogic componentInstanceBL, ComponentsUtils componentsUtils,
106         ServletUtils servletUtils, ResourceImportManager resourceImportManager) {
107         super(userBusinessLogic, componentsUtils);
108         this.servletUtils = servletUtils;
109         this.resourceImportManager = resourceImportManager;
110         this.componentInstanceBusinessLogic = componentInstanceBL;
111     }
112
113     protected void init() {
114     }
115
116     protected void validateResourceDoesNotExist(Wrapper<Response> responseWrapper, User user, String resourceName) {
117         if (resourceImportManager.isResourceExist(resourceName)) {
118             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESOURCE_ALREADY_EXISTS);
119             Response errorResponse = buildErrorResponse(responseFormat);
120             getComponentsUtils().auditResource(responseFormat, user, resourceName, AuditingActionEnum.IMPORT_RESOURCE);
121             responseWrapper.setInnerElement(errorResponse);
122         }
123     }
124
125     protected void validateUserExist(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, String userUserId) {
126         log.debug("get user {} from DB", userUserId);
127         // get user details
128         if (userUserId == null) {
129             log.info("user userId is null");
130             Response response = returnMissingInformation(new User());
131             responseWrapper.setInnerElement(response);
132         }
133
134         else {
135             UserBusinessLogic userAdmin = getServletUtils().getUserAdmin();
136             try {
137                 User user = userAdmin.getUser(userUserId);
138                 userWrapper.setInnerElement(user);
139             } catch (ComponentException ce) {
140                 log.info("user is not listed. userId={}", userUserId);
141                 User user = new User();
142                 user.setUserId(userUserId);
143                 Response response = returnMissingInformation(user);
144                 responseWrapper.setInnerElement(response);
145             }
146         }
147     }
148
149     protected Response returnMissingInformation(User user) {
150         ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_INFORMATION);
151         getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
152         return buildErrorResponse(responseFormat);
153     }
154
155     protected void validateDataNotNull(Wrapper<Response> responseWrapper, Object... dataParams) {
156         for (Object dataElement : dataParams) {
157             if (dataElement == null) {
158                 log.info("Invalid body was received.");
159                 Response response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
160                 responseWrapper.setInnerElement(response);
161                 break;
162             }
163         }
164
165     }
166
167     protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user) {
168         log.debug("validate user role");
169         if (!user.getRole().equals(Role.ADMIN.name()) && !user.getRole().equals(Role.DESIGNER.name())) {
170             log.info("user is not in appropriate role to perform action");
171             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
172             log.debug("audit before sending response");
173             getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
174
175             Response response = buildErrorResponse(responseFormat);
176             errorResponseWrapper.setInnerElement(response);
177         }
178
179     }
180
181     protected void validateZip(final Wrapper<Response> responseWrapper, final File zipFile, final String payloadName) {
182         if (StringUtils.isEmpty(payloadName)) {
183             log.info("Invalid JSON was received. Payload name is empty");
184             final Response errorResponse =
185                 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
186             responseWrapper.setInnerElement(errorResponse);
187             return;
188         }
189         final Map<String, byte[]> unzippedFolder;
190         try {
191             unzippedFolder = ZipUtils.readZip(zipFile, false);
192         } catch (final ZipException e) {
193             log.error("Could not read ZIP file '{}' for validation", zipFile.getName(), e);
194             final Response errorResponse =
195                 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
196             responseWrapper.setInnerElement(errorResponse);
197             return;
198         }
199         if (!unzippedFolder.containsKey(payloadName)) {
200             log.info("Could no find payload '{}' in ZIP file '{}'", payloadName, zipFile.getName());
201             final Response errorResponse =
202                 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
203             responseWrapper.setInnerElement(errorResponse);
204         }
205
206
207     }
208
209     protected void validateCsar(final Wrapper<Response> responseWrapper, final File csarFile, final String payloadName) {
210         if (StringUtils.isEmpty(payloadName)) {
211             log.info("Invalid JSON was received. Payload name is empty");
212             Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
213             responseWrapper.setInnerElement(errorResponse);
214             return;
215         }
216         final Map<String, byte[]> unzippedFolder;
217         try {
218             unzippedFolder = ZipUtils.readZip(csarFile, false);
219         } catch (final ZipException e) {
220             log.error("Could not read CSAR file '{}' for validation", csarFile.getName(), e);
221             final Response errorResponse =
222                 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
223             responseWrapper.setInnerElement(errorResponse);
224             return;
225         }
226         if (unzippedFolder.isEmpty()) {
227             log.info("The CSAR file is empty");
228             Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
229             responseWrapper.setInnerElement(errorResponse);
230         }
231
232     }
233
234     protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
235         extractZipContents(yamlStringWrapper, file);
236     }
237
238     public static void extractZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
239         final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
240         String ymlName = unzippedFolder.keySet().iterator().next();
241         fillToscaTemplateFromZip(yamlStringWrapper, ymlName, file);
242     }
243
244     private static void fillToscaTemplateFromZip(final Wrapper<String> yamlStringWrapper, final String payloadName,
245                                                  final File file) throws ZipException {
246         final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
247         final byte[] yamlFileInBytes = unzippedFolder.get(payloadName);
248         final String yamlAsString = new String(yamlFileInBytes, StandardCharsets.UTF_8);
249         log.debug("received yaml: {}", yamlAsString);
250         yamlStringWrapper.setInnerElement(yamlAsString);
251     }
252
253     protected void fillPayloadDataFromFile(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfoWrapper, File file)  {
254         try(InputStream fileInputStream = new FileInputStream(file)){
255
256             byte [] data = new byte[(int)file.length()];
257             if( fileInputStream.read(data) == -1){
258                 log.info("Invalid json was received.");
259                 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
260
261                 Response errorResp = buildErrorResponse(responseFormat);
262                 responseWrapper.setInnerElement(errorResp);
263             }
264             String payloadData =  Base64.encodeBase64String(data);
265             uploadResourceInfoWrapper.setPayloadData(payloadData);
266
267
268
269         } catch (IOException e) {
270             log.info("Invalid json was received or Error while closing input Stream.");
271             log.debug("Invalid json was received or Error while closing input Stream. {}", e.getMessage(), e);
272             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
273
274             Response errorResp = buildErrorResponse(responseFormat);
275             responseWrapper.setInnerElement(errorResp);
276
277         }
278     }
279
280     protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user, ResourceAuthorityTypeEnum resourceAuthority) {
281         log.debug("validate user role");
282         if (resourceAuthority == ResourceAuthorityTypeEnum.NORMATIVE_TYPE_BE) {
283             if (!user.getRole().equals(Role.ADMIN.name())) {
284                 log.info("user is not in appropriate role to perform action");
285                 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
286                 log.debug("audit before sending response");
287                 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
288
289                 Response response = buildErrorResponse(responseFormat);
290                 errorResponseWrapper.setInnerElement(response);
291             }
292         } else {
293             validateUserRole(errorResponseWrapper, user);
294         }
295
296     }
297
298     protected void validateAndFillResourceJson(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, User user, ResourceAuthorityTypeEnum resourceAuthorityEnum, String resourceInfo) {
299         boolean isValid;
300         try {
301             log.debug("The received json is {}", resourceInfo);
302             UploadResourceInfo resourceInfoObject = gson.fromJson(resourceInfo, UploadResourceInfo.class);
303             if (resourceInfoObject == null) {
304                 isValid = false;
305             } else {
306                 if (!resourceAuthorityEnum.isBackEndImport()) {
307                     isValid = resourceInfoObject.getPayloadName() != null && !resourceInfoObject.getPayloadName().isEmpty();
308                     //only resource name is checked
309                 } else {
310                     isValid = true;
311                 }
312                 uploadResourceInfoWrapper.setInnerElement(resourceInfoObject);
313             }
314
315         } catch (JsonSyntaxException e) {
316             log.debug("Invalid json was received. {}", e.getMessage(), e);
317             isValid = false;
318
319         }
320         if (!isValid) {
321             log.info("Invalid json was received.");
322             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
323             getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
324             Response errorResp = buildErrorResponse(responseFormat);
325             responseWrapper.setInnerElement(errorResp);
326         }
327     }
328
329     protected void validateAuthorityType(Wrapper<Response> responseWrapper, String authorityType) {
330         log.debug("The received authority type is {}", authorityType);
331         ResourceAuthorityTypeEnum authorityTypeEnum = ResourceAuthorityTypeEnum.findByUrlPath(authorityType);
332         if (authorityTypeEnum == null) {
333             log.info("Invalid authority type was received.");
334             Response errorResp = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
335             responseWrapper.setInnerElement(errorResp);
336         }
337     }
338
339     public ServletUtils getServletUtils() {
340         return servletUtils;
341     }
342
343     public Gson getGson() {
344         return getServletUtils().getGson();
345     }
346
347     public ComponentsUtils getComponentsUtils() {
348         return getServletUtils().getComponentsUtils();
349     }
350
351     protected void validatePayloadIsTosca(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
352         log.debug("checking payload is valid tosca");
353         boolean isValid;
354         Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
355         Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
356
357         if (findFirstToscaStringElement.isRight()) {
358             isValid = false;
359         } else {
360             String defenitionVersionFound = findFirstToscaStringElement.left().value();
361             if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
362                 isValid = false;
363             } else {
364                 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
365             }
366         }
367
368         if (!isValid) {
369             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
370             Response errorResponse = buildErrorResponse(responseFormat);
371             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
372             responseWrapper.setInnerElement(errorResponse);
373         }
374
375     }
376
377     protected void validatePayloadIsYml(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaTamplatePayload) {
378         log.debug("checking tosca template is valid yml");
379         YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
380         boolean isYamlValid = yamlConvertor.isValidYaml(toscaTamplatePayload.getBytes());
381         if (!isYamlValid) {
382             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
383             Response errorResponse = buildErrorResponse(responseFormat);
384             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
385             responseWrapper.setInnerElement(errorResponse);
386         }
387     }
388
389     /**
390      * Gets the Resource type from the given node type name.
391      *
392      * @param nodeTypeFullName - Node type Name
393      * @return Resource Type name
394      */
395     private String getResourceType(final String nodeTypeFullName) {
396
397         final Optional<String> nodeTypeNamePrefix = getNodeTypeNamePrefix(nodeTypeFullName);
398         if (nodeTypeNamePrefix.isPresent()) {
399             final String nameWithouNamespacePrefix = nodeTypeFullName.substring(nodeTypeNamePrefix.get().length());
400             final String[] findTypes = nameWithouNamespacePrefix.split("\\.");
401             if (findTypes.length > 0) {
402                 final ResourceTypeEnum resourceType = ResourceTypeEnum.getType(findTypes[0].toUpperCase());
403                 if (resourceType != null) {
404                     return resourceType.name();
405                 }
406             }
407         }
408         return ResourceTypeEnum.VFC.name();
409     }
410
411     /**
412      * Extracts the Node Type Name prefix from the given Node Type Name.
413      * @param nodeName - Node Type Name
414      * @return Node Type Name prefix
415      */
416     private Optional<String> getNodeTypeNamePrefix(final String nodeName) {
417         final List<String> definedNodeTypeNamespaceList = ConfigurationManager.getConfigurationManager()
418             .getConfiguration().getDefinedResourceNamespace();
419         for (final String validNamespace : definedNodeTypeNamespaceList) {
420             if (nodeName.startsWith(validNamespace)) {
421                 return Optional.of(validNamespace);
422             }
423         }
424         return Optional.empty();
425     }
426
427     protected void validatePayloadNameSpace(final Wrapper<Response> responseWrapper,
428                                             final UploadResourceInfo resourceInfo,
429                                             final User user, final String toscaPayload) {
430         boolean isValid;
431         String namespace = "";
432         final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
433         final Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
434         if (toscaElement.isRight() || toscaElement.left().value().size() != 1) {
435             isValid = false;
436         } else {
437             namespace = toscaElement.left().value().keySet().iterator().next();
438             isValid = getNodeTypeNamePrefix(namespace).isPresent();
439         }
440         if (!isValid) {
441             final ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_NAMESPACE);
442             final Response errorResponse = buildErrorResponse(responseFormat);
443             getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
444             responseWrapper.setInnerElement(errorResponse);
445         } else {
446             resourceInfo.setResourceType(getResourceType(namespace));
447         }
448     }
449
450     private void validatePayloadIsSingleResource(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
451         log.debug("checking payload contains single resource");
452         boolean isValid;
453         Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
454         Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
455         if (toscaElement.isRight()) {
456             isValid = false;
457         } else {
458             isValid = toscaElement.left().value().size() == 1;
459         }
460
461         if (!isValid) {
462             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_SINGLE_RESOURCE);
463             Response errorResponse = buildErrorResponse(responseFormat);
464             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
465             responseWrapper.setInnerElement(errorResponse);
466         }
467
468     }
469
470     private void validatePayloadIsNotService(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaPayload) {
471         log.debug("checking payload is not a tosca service");
472         Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
473         Either<Object, ResultStatusEnum> toscaElement = ImportUtils.findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL);
474
475         if (toscaElement.isLeft()) {
476             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_RESOURCE_TOSCA_TEMPLATE);
477             Response errorResponse = buildErrorResponse(responseFormat);
478             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
479             responseWrapper.setInnerElement(errorResponse);
480         }
481
482     }
483
484     private void validateToscaTemplatePayloadName(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
485         String toscaTemplatePayloadName = uploadResourceInfo.getPayloadName();
486         boolean isValidSuffix = false;
487         if (toscaTemplatePayloadName != null && !toscaTemplatePayloadName.isEmpty()) {
488             for (String validSuffix : TOSCA_YML_CSAR_VALID_SUFFIX) {
489                 isValidSuffix = isValidSuffix || toscaTemplatePayloadName.toLowerCase().endsWith(validSuffix);
490             }
491         }
492         if (!isValidSuffix) {
493             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_FILE_EXTENSION);
494             Response errorResponse = buildErrorResponse(responseFormat);
495             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
496             responseWrapper.setInnerElement(errorResponse);
497         }
498
499     }
500
501     private void validateMD5(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfo, HttpServletRequest request, String resourceInfoJsonString) {
502         boolean isValid;
503         String recievedMD5 = request.getHeader(Constants.MD5_HEADER);
504         if (recievedMD5 == null) {
505             isValid = false;
506         } else {
507             String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(resourceInfoJsonString);
508             isValid = calculateMD5.equals(recievedMD5);
509         }
510         if (!isValid) {
511             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_CHECKSUM);
512             Response errorResponse = buildErrorResponse(responseFormat);
513             getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
514             responseWrapper.setInnerElement(errorResponse);
515         }
516     }
517
518     ComponentTypeEnum validateComponentType(String componentType) {
519         if (componentType == null) {
520             throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR);
521         }
522         if (ComponentTypeEnum.RESOURCE_PARAM_NAME.equalsIgnoreCase(componentType)) {
523             return ComponentTypeEnum.RESOURCE;
524         }
525         if (ComponentTypeEnum.SERVICE_PARAM_NAME.equalsIgnoreCase(componentType)) {
526             return ComponentTypeEnum.SERVICE;
527         }
528         log.debug("Invalid componentType:{}", componentType);
529         throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR, componentType);
530     }
531
532
533     ComponentTypeEnum convertToComponentType(String componentType) {
534         return validateComponentType(componentType);
535     }
536
537     private void fillToscaTemplateFromJson(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo resourceInfo) {
538         if (resourceInfo.getPayloadData() == null || resourceInfo.getPayloadData().isEmpty()) {
539             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_PAYLOAD);
540             Response errorResponse = buildErrorResponse(responseFormat);
541             getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
542             responseWrapper.setInnerElement(errorResponse);
543         } else {
544             String toscaPayload = resourceInfo.getPayloadData();
545             String decodedPayload = new String(Base64.decodeBase64(toscaPayload));
546             yamlStringWrapper.setInnerElement(decodedPayload);
547         }
548
549     }
550
551     void fillPayload(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, String resourceInfoJsonString, ResourceAuthorityTypeEnum resourceAuthorityEnum,
552             File file) throws ZipException {
553
554         if (responseWrapper.isEmpty()) {
555             if (resourceAuthorityEnum.isBackEndImport()) {
556                 // PrePayload Validations
557                 if (responseWrapper.isEmpty()) {
558                     validateDataNotNull(responseWrapper, file, resourceInfoJsonString);
559                 }
560                 if(!resourceAuthorityEnum.equals(ResourceAuthorityTypeEnum.CSAR_TYPE_BE)){
561                     if (responseWrapper.isEmpty()) {
562                         validateZip(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
563                     }
564
565                     // Fill PayLoad From File
566                     if (responseWrapper.isEmpty()) {
567                         fillToscaTemplateFromZip(yamlStringWrapper, uploadResourceInfoWrapper.getInnerElement().getPayloadName(), file);
568                     }
569                 }else{
570
571                     if (responseWrapper.isEmpty()) {
572                         validateCsar(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
573                     }
574
575                     // Fill PayLoad From File
576                     if (responseWrapper.isEmpty()) {
577                         fillPayloadDataFromFile(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), file);
578                     }
579
580                 }
581
582             } else {
583                 // Fill PayLoad From JSON
584                 if (responseWrapper.isEmpty()) {
585                     fillToscaTemplateFromJson(responseWrapper, yamlStringWrapper, user, uploadResourceInfoWrapper.getInnerElement());
586                 }
587             }
588
589         }
590
591     }
592
593     protected void specificResourceAuthorityValidations(final Wrapper<Response> responseWrapper,
594                                                         final Wrapper<UploadResourceInfo> uploadResourceInfoWrapper,
595                                                         final Wrapper<String> yamlStringWrapper, final User user,
596                                                         final HttpServletRequest request, final String resourceInfoJsonString,
597                                                         final ResourceAuthorityTypeEnum resourceAuthorityEnum) {
598
599         if (responseWrapper.isEmpty()) {
600             // UI Only Validation
601             if (!resourceAuthorityEnum.isBackEndImport()) {
602                 importUIValidations(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, request, resourceInfoJsonString);
603             }
604
605             // User Defined Type Resources
606             if (resourceAuthorityEnum.isUserTypeResource() && !CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {
607                 if (responseWrapper.isEmpty()) {
608                     validatePayloadNameSpace(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, yamlStringWrapper.getInnerElement());
609                 }
610
611             }
612         }
613     }
614
615     void commonGeneralValidations(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, ResourceAuthorityTypeEnum resourceAuthorityEnum, String userId,
616                                   String resourceInfoJsonString) {
617
618         if (responseWrapper.isEmpty()) {
619             validateUserExist(responseWrapper, userWrapper, userId);
620         }
621
622         if (responseWrapper.isEmpty()) {
623             validateUserRole(responseWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum);
624         }
625
626         if (responseWrapper.isEmpty()) {
627             validateAndFillResourceJson(responseWrapper, uploadResourceInfoWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum, resourceInfoJsonString);
628         }
629
630         if (responseWrapper.isEmpty()) {
631             validateToscaTemplatePayloadName(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
632         }
633         if (responseWrapper.isEmpty()) {
634             validateResourceType(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
635         }
636
637     }
638
639     private void validateResourceType(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
640         String resourceType = uploadResourceInfo.getResourceType();
641         if (resourceType == null || !ResourceTypeEnum.containsName(resourceType)) {
642             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
643             Response errorResponse = buildErrorResponse(responseFormat);
644             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
645             responseWrapper.setInnerElement(errorResponse);
646         }
647     }
648
649     private void importUIValidations(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, HttpServletRequest request, String resourceInfoJsonString) {
650         if (responseWrapper.isEmpty()) {
651             validateMD5(responseWrapper, user, resourceInfo, request, resourceInfoJsonString);
652         }
653         if (responseWrapper.isEmpty() && request != null && request.getMethod() != null && request.getMethod().equals("POST")) {
654             validateResourceDoesNotExist(responseWrapper, user, resourceInfo.getName());
655         }
656     }
657
658     void commonPayloadValidations(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo uploadResourceInfo) {
659
660         if (responseWrapper.isEmpty()) {
661             validatePayloadIsYml(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
662         }
663         if (responseWrapper.isEmpty()) {
664             validatePayloadIsTosca(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
665         }
666         if (responseWrapper.isEmpty()) {
667             validatePayloadIsNotService(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
668         }
669         if (responseWrapper.isEmpty()) {
670             validatePayloadIsSingleResource(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
671         }
672     }
673
674
675     void handleImport(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfoObject, String yamlAsString, ResourceAuthorityTypeEnum authority, boolean createNewVersion, String resourceUniqueId) {
676         ImmutablePair<Resource, ActionStatus> createOrUpdateResponse = null;
677         Response response = null;
678         Object representation = null;
679         ImmutablePair<Resource, ActionStatus> importedResourceStatus = null;
680         if (CsarValidationUtils.isCsarPayloadName(resourceInfoObject.getPayloadName())) {
681             log.debug("import resource from csar");
682             importedResourceStatus = importResourceFromUICsar(resourceInfoObject, user, resourceUniqueId);
683         } else if (!authority.isUserTypeResource()) {
684             log.debug("import normative type resource");
685             createOrUpdateResponse = resourceImportManager.importNormativeResource(yamlAsString, resourceInfoObject, user, createNewVersion, true);
686         } else {
687             log.debug("import user resource (not normative type)");
688             createOrUpdateResponse = resourceImportManager.importUserDefinedResource(yamlAsString, resourceInfoObject, user,  false);
689         }
690         if (createOrUpdateResponse!= null){
691             importedResourceStatus = createOrUpdateResponse;
692         }
693         if(importedResourceStatus != null){
694             try {
695                 representation = RepresentationUtils.toRepresentation(importedResourceStatus.left);
696             } catch (IOException e) {
697                 log.debug("Error while building resource representation : {}", e.getMessage(), e);
698             }
699             response = buildOkResponse(getComponentsUtils().getResponseFormat(importedResourceStatus.right), representation);
700         }
701         responseWrapper.setInnerElement(response);
702     }
703
704     private ImmutablePair<Resource, ActionStatus> importResourceFromUICsar(UploadResourceInfo resourceInfoObject, User user, String resourceUniqueId) {
705
706         Resource newResource;
707         ActionStatus actionStatus;
708         Resource resource = new Resource();
709         String payloadName = resourceInfoObject.getPayloadName();
710         fillResourceFromResourceInfoObject(resource, resourceInfoObject);
711
712         Map<String, byte[]> csarUIPayload = getCsarFromPayload(resourceInfoObject);
713         getAndValidateCsarYaml(csarUIPayload, resource, user, payloadName);
714
715         if (resourceUniqueId == null || resourceUniqueId.isEmpty()) {
716             newResource = resourceImportManager.getResourceBusinessLogic().createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, csarUIPayload, payloadName);
717             actionStatus = ActionStatus.CREATED;
718         } else {
719             newResource = resourceImportManager.getResourceBusinessLogic().validateAndUpdateResourceFromCsar(resource, user, csarUIPayload, payloadName, resourceUniqueId);
720             actionStatus = ActionStatus.OK;
721         }
722         return new ImmutablePair<>(newResource, actionStatus);
723     }
724
725     private Resource throwComponentException(ResponseFormat responseFormat) {
726         throw new ByResponseFormatComponentException(responseFormat);
727     }
728
729     private void getAndValidateCsarYaml(Map<String, byte[]> csarUIPayload, Resource resource, User user, String csarUUID) {
730
731         Either<ImmutablePair<String, String>, ResponseFormat> getToscaYamlRes = CsarValidationUtils.getToscaYaml(csarUIPayload, csarUUID, getComponentsUtils());
732
733         if (getToscaYamlRes.isRight()) {
734             ResponseFormat responseFormat = getToscaYamlRes.right().value();
735             log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat);
736             BeEcompErrorManager.getInstance().logBeDaoSystemError("Creating resource from CSAR: fetching CSAR with id " + csarUUID + " failed");
737             getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.CREATE_RESOURCE);
738             throwComponentException(responseFormat);
739         }
740         String toscaYaml = getToscaYamlRes.left().value().getValue();
741
742         log.debug("checking tosca template is valid yml");
743         YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
744         boolean isValid = yamlConvertor.isValidYaml(toscaYaml.getBytes());
745         if (!isValid) {
746             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
747             getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
748             throwComponentException(responseFormat);
749         }
750
751         log.debug("checking payload is valid tosca");
752         Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaYaml);
753         Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
754
755         if (findFirstToscaStringElement.isRight()) {
756             isValid = false;
757         } else {
758             String defenitionVersionFound = findFirstToscaStringElement.left().value();
759             if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
760                 isValid = false;
761             } else {
762                 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
763             }
764         }
765
766         if (!isValid) {
767             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
768             getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
769             throwComponentException(responseFormat);
770         }
771     }
772
773     private void fillResourceFromResourceInfoObject(Resource resource, UploadResourceInfo resourceInfoObject) {
774         resourceImportManager.populateResourceMetadata(resourceInfoObject, resource);
775         fillArtifacts(resource, resourceInfoObject);
776
777     }
778
779     private void fillArtifacts(Resource resource, UploadResourceInfo resourceInfoObject) {
780         if (resource != null && resourceInfoObject != null) {
781             List<UploadArtifactInfo> artifactList = resourceInfoObject.getArtifactList();
782             if (artifactList != null) {
783                 Map<String, ArtifactDefinition> artifactsHM = new HashMap<>();
784                 for (UploadArtifactInfo artifact : artifactList) {
785                     ArtifactDefinition artifactDef = new ArtifactDefinition();
786                     artifactDef.setArtifactName(artifact.getArtifactName());
787                     artifactDef.setArtifactType(artifact.getArtifactType().getType());
788                     artifactDef.setDescription(artifact.getArtifactDescription());
789                     artifactDef.setPayloadData(artifact.getArtifactData());
790                     artifactDef.setArtifactRef(artifact.getArtifactPath());
791                     artifactsHM.put(artifactDef.getArtifactName(), artifactDef);
792                 }
793                 resource.setArtifacts(artifactsHM);
794             }
795         }
796     }
797
798     private Map<String, byte[]> getCsarFromPayload(UploadResourceInfo innerElement) {
799         String csarUUID = innerElement.getPayloadName();
800         String payloadData = innerElement.getPayloadData();
801         if (payloadData == null) {
802             log.info("Failed to decode received csar {}", csarUUID);
803             throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
804         }
805
806         byte[] decodedPayload = Base64.decodeBase64(payloadData.getBytes(StandardCharsets.UTF_8));
807         if (decodedPayload == null) {
808             log.info("Failed to decode received csar {}", csarUUID);
809             throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
810         }
811
812         Map<String, byte[]> csar = null;
813         try {
814             csar = ZipUtils.readZip(decodedPayload, false);
815         } catch (final ZipException e) {
816             log.info("Failed to unzip received csar {}", csarUUID, e);
817         }
818         if (MapUtils.isEmpty(csar)) {
819         }
820         return csar;
821     }
822
823     void validateInputStream(final HttpServletRequest request, Wrapper<String> dataWrapper, Wrapper<ResponseFormat> errorWrapper) throws IOException {
824         InputStream inputStream = request.getInputStream();
825         byte[] bytes = IOUtils.toByteArray(inputStream);
826         if (bytes == null || bytes.length == 0) {
827             log.info("Empty body was sent.");
828             errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
829         } else {
830             dataWrapper.setInnerElement(new String(bytes, StandardCharsets.UTF_8));
831         }
832
833     }
834
835     <T> void validateClassParse(String data, Wrapper<T> parsedClassWrapper, Supplier<Class<T>> classGen, Wrapper<ResponseFormat> errorWrapper) {
836         try {
837             T parsedClass = gson.fromJson(data, classGen.get());
838             if (parsedClass == null) {
839                 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
840             } else {
841                 parsedClassWrapper.setInnerElement(parsedClass);
842             }
843         } catch (JsonSyntaxException e) {
844             log.debug("Failed to decode received {} {} to object.", classGen.get().getName(), data, e);
845             errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
846         }
847     }
848
849     void validateComponentInstanceBusinessLogic(HttpServletRequest request, String containerComponentType, Wrapper<ComponentInstanceBusinessLogic> blWrapper, Wrapper<ResponseFormat> errorWrapper) {
850         ServletContext context = request.getSession().getServletContext();
851         ComponentInstanceBusinessLogic componentInstanceLogic = getComponentInstanceBL(context);
852         if (componentInstanceLogic == null) {
853             log.debug("Unsupported component type {}", containerComponentType);
854             errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
855         } else {
856             blWrapper.setInnerElement(componentInstanceLogic);
857         }
858     }
859
860     <T> Response buildResponseFromElement(Wrapper<ResponseFormat> errorWrapper, Wrapper<T> attributeWrapper) throws IOException {
861         Response response;
862         if (errorWrapper.isEmpty()) {
863             ObjectMapper mapper = new ObjectMapper();
864             String result = mapper.writeValueAsString(attributeWrapper.getInnerElement());
865             response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
866         } else {
867             response = buildErrorResponse(errorWrapper.getInnerElement());
868         }
869         return response;
870     }
871
872     protected void validateXECOMPInstanceIDHeader(String instanceIdHeader, Wrapper<ResponseFormat> responseWrapper) {
873         ResponseFormat responseFormat;
874         if(StringUtils.isEmpty(instanceIdHeader) ){
875             log.debug("Missing X-ECOMP-InstanceID header");
876             responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
877             responseWrapper.setInnerElement(responseFormat);
878         }
879     }
880
881     protected void validateHttpCspUserIdHeader(String header, Wrapper<ResponseFormat> responseWrapper) {
882         ResponseFormat responseFormat;
883         if( StringUtils.isEmpty(header)){
884             log.debug("MissingUSER_ID");
885             responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_USER_ID);
886             responseWrapper.setInnerElement(responseFormat);
887         }
888     }
889
890     <T> Either<T, ResponseFormat> parseToObject(String json, Supplier<Class<T>> classSupplier) {
891
892         try {
893             T object = RepresentationUtils.fromRepresentation(json, classSupplier.get());
894             return Either.left(object);
895         } catch (Exception e) {
896             log.debug("Failed to parse json to {} object", classSupplier.get().getName(), e);
897             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
898             return Either.right(responseFormat);
899         }
900     }
901
902     public <T> Either<List<T>, ResponseFormat> parseListOfObjects(String json, Type type) {
903         try {
904             List<T> listOfObjects = gson.fromJson(json, type);
905             return Either.left(listOfObjects);
906         } catch (Exception e) {
907             log.debug("Failed to parse json to {} object", type.getClass().getName(), e);
908             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
909             return Either.right(responseFormat);
910         }
911     }
912     protected void validateNotEmptyBody(String data) {
913         if (StringUtils.isEmpty(data)) {
914             throw new ByActionStatusComponentException(ActionStatus.MISSING_BODY);
915         }
916     }
917 }