2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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 * ================================================================================
23 package org.openecomp.sdc.be.servlets;
25 import com.fasterxml.jackson.databind.ObjectMapper;
26 import com.google.gson.Gson;
27 import com.google.gson.JsonSyntaxException;
28 import fj.data.Either;
30 import java.io.FileInputStream;
31 import java.io.FileNotFoundException;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.lang.reflect.Type;
35 import java.nio.charset.StandardCharsets;
36 import java.util.Arrays;
37 import java.util.HashMap;
38 import java.util.List;
40 import java.util.function.Supplier;
41 import javax.servlet.ServletContext;
42 import javax.servlet.http.HttpServletRequest;
43 import javax.ws.rs.core.Response;
44 import org.apache.commons.codec.binary.Base64;
45 import org.apache.commons.collections4.MapUtils;
46 import org.apache.commons.io.IOUtils;
47 import org.apache.commons.lang3.StringUtils;
48 import org.apache.commons.lang3.tuple.ImmutablePair;
49 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
50 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
51 import org.openecomp.sdc.be.components.impl.ImportUtils;
52 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
53 import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
54 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
55 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
56 import org.openecomp.sdc.be.config.BeEcompErrorManager;
57 import org.openecomp.sdc.be.dao.api.ActionStatus;
58 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
59 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
60 import org.openecomp.sdc.be.impl.ComponentsUtils;
61 import org.openecomp.sdc.be.impl.ServletUtils;
62 import org.openecomp.sdc.be.model.ArtifactDefinition;
63 import org.openecomp.sdc.be.model.Resource;
64 import org.openecomp.sdc.be.model.UploadResourceInfo;
65 import org.openecomp.sdc.be.model.User;
66 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
67 import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
68 import org.openecomp.sdc.be.user.IUserBusinessLogic;
69 import org.openecomp.sdc.be.user.Role;
70 import org.openecomp.sdc.be.user.UserBusinessLogic;
71 import org.openecomp.sdc.be.utils.TypeUtils;
72 import org.openecomp.sdc.common.api.Constants;
73 import org.openecomp.sdc.common.api.UploadArtifactInfo;
74 import org.openecomp.sdc.common.datastructure.Wrapper;
75 import org.openecomp.sdc.common.log.wrappers.Logger;
76 import org.openecomp.sdc.common.util.GeneralUtility;
77 import org.openecomp.sdc.common.util.YamlToObjectConverter;
78 import org.openecomp.sdc.common.zip.ZipUtils;
79 import org.openecomp.sdc.common.zip.exception.ZipException;
80 import org.openecomp.sdc.exception.ResponseFormat;
81 import org.yaml.snakeyaml.Yaml;
83 public abstract class AbstractValidationsServlet extends BeGenericServlet {
85 private static final Logger log = Logger.getLogger(AbstractValidationsServlet.class);
86 private static final String TOSCA_SIMPLE_YAML_PREFIX = "tosca_simple_yaml_";
87 private static final List<String> TOSCA_DEFINITION_VERSIONS = Arrays.asList(TOSCA_SIMPLE_YAML_PREFIX + "1_0_0", TOSCA_SIMPLE_YAML_PREFIX + "1_1_0", "tosca_simple_profile_for_nfv_1_0_0", TOSCA_SIMPLE_YAML_PREFIX + "1_0", TOSCA_SIMPLE_YAML_PREFIX + "1_1");
88 private static final List<String> TOSCA_YML_CSAR_VALID_SUFFIX = Arrays.asList(".yml", ".yaml", ".csar");
90 protected ServletUtils servletUtils;
91 protected ResourceImportManager resourceImportManager;
92 protected final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
95 public AbstractValidationsServlet(UserBusinessLogic userBusinessLogic,
96 ComponentInstanceBusinessLogic componentInstanceBL, ComponentsUtils componentsUtils,
97 ServletUtils servletUtils, ResourceImportManager resourceImportManager) {
98 super(userBusinessLogic, componentsUtils);
99 this.servletUtils = servletUtils;
100 this.resourceImportManager = resourceImportManager;
101 this.componentInstanceBusinessLogic = componentInstanceBL;
104 protected void init() {
107 protected void validateResourceDoesNotExist(Wrapper<Response> responseWrapper, User user, String resourceName) {
108 if (resourceImportManager.isResourceExist(resourceName)) {
109 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESOURCE_ALREADY_EXISTS);
110 Response errorResponse = buildErrorResponse(responseFormat);
111 getComponentsUtils().auditResource(responseFormat, user, resourceName, AuditingActionEnum.IMPORT_RESOURCE);
112 responseWrapper.setInnerElement(errorResponse);
116 protected void validateUserExist(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, String userUserId) {
117 log.debug("get user {} from DB", userUserId);
119 if (userUserId == null) {
120 log.info("user userId is null");
121 Response response = returnMissingInformation(new User());
122 responseWrapper.setInnerElement(response);
126 IUserBusinessLogic userAdmin = getServletUtils().getUserAdmin();
127 Either<User, ActionStatus> eitherCreator = userAdmin.getUser(userUserId, false);
128 if (eitherCreator.isRight()) {
129 log.info("user is not listed. userId={}", userUserId);
130 User user = new User();
131 user.setUserId(userUserId);
132 Response response = returnMissingInformation(user);
133 responseWrapper.setInnerElement(response);
135 userWrapper.setInnerElement(eitherCreator.left().value());
140 protected Response returnMissingInformation(User user) {
141 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_INFORMATION);
142 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
143 return buildErrorResponse(responseFormat);
146 protected void validateDataNotNull(Wrapper<Response> responseWrapper, Object... dataParams) {
147 for (Object dataElement : dataParams) {
148 if (dataElement == null) {
149 log.info("Invalid body was received.");
150 Response response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
151 responseWrapper.setInnerElement(response);
158 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user) {
159 log.debug("validate user role");
160 if (!user.getRole().equals(Role.ADMIN.name()) && !user.getRole().equals(Role.DESIGNER.name())) {
161 log.info("user is not in appropriate role to perform action");
162 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
163 log.debug("audit before sending response");
164 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
166 Response response = buildErrorResponse(responseFormat);
167 errorResponseWrapper.setInnerElement(response);
172 protected void validateZip(final Wrapper<Response> responseWrapper, final File zipFile, final String payloadName) {
173 if (StringUtils.isEmpty(payloadName)) {
174 log.info("Invalid JSON was received. Payload name is empty");
175 final Response errorResponse =
176 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
177 responseWrapper.setInnerElement(errorResponse);
180 final Map<String, byte[]> unzippedFolder;
182 unzippedFolder = ZipUtils.readZip(zipFile, false);
183 } catch (final ZipException e) {
184 log.error("Could not read ZIP file '{}' for validation", zipFile.getName(), e);
185 final Response errorResponse =
186 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
187 responseWrapper.setInnerElement(errorResponse);
190 if (!unzippedFolder.containsKey(payloadName)) {
191 log.info("Could no find payload '{}' in ZIP file '{}'", payloadName, zipFile.getName());
192 final Response errorResponse =
193 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
194 responseWrapper.setInnerElement(errorResponse);
200 protected void validateCsar(final Wrapper<Response> responseWrapper, final File csarFile, final String payloadName) {
201 if (StringUtils.isEmpty(payloadName)) {
202 log.info("Invalid JSON was received. Payload name is empty");
203 Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
204 responseWrapper.setInnerElement(errorResponse);
207 final Map<String, byte[]> unzippedFolder;
209 unzippedFolder = ZipUtils.readZip(csarFile, false);
210 } catch (final ZipException e) {
211 log.error("Could not read CSAR file '{}' for validation", csarFile.getName(), e);
212 final Response errorResponse =
213 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
214 responseWrapper.setInnerElement(errorResponse);
217 if (unzippedFolder.isEmpty()) {
218 log.info("The CSAR file is empty");
219 Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
220 responseWrapper.setInnerElement(errorResponse);
225 protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
226 extractZipContents(yamlStringWrapper, file);
229 public static void extractZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
230 final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
231 String ymlName = unzippedFolder.keySet().iterator().next();
232 fillToscaTemplateFromZip(yamlStringWrapper, ymlName, file);
235 private static void fillToscaTemplateFromZip(Wrapper<String> yamlStringWrapper, String payloadName, File file) {
236 Map<String, byte[]> unzippedFolder = null;
238 unzippedFolder = ZipUtils.readZip(file, false);
239 } catch (final ZipException e) {
240 log.info("Failed to unzip file", e);
242 byte[] yamlFileInBytes = unzippedFolder.get(payloadName);
243 String yamlAsString = new String(yamlFileInBytes, StandardCharsets.UTF_8);
244 log.debug("received yaml: {}", yamlAsString);
245 yamlStringWrapper.setInnerElement(yamlAsString);
248 protected void fillPayloadDataFromFile(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfoWrapper, File file) {
249 try(InputStream fileInputStream = new FileInputStream(file)){
251 byte [] data = new byte[(int)file.length()];
252 if( fileInputStream.read(data) == -1){
253 log.info("Invalid json was received.");
254 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
256 Response errorResp = buildErrorResponse(responseFormat);
257 responseWrapper.setInnerElement(errorResp);
259 String payloadData = Base64.encodeBase64String(data);
260 uploadResourceInfoWrapper.setPayloadData(payloadData);
264 } catch (IOException e) {
265 log.info("Invalid json was received or Error while closing input Stream.");
266 log.debug("Invalid json was received or Error while closing input Stream. {}", e.getMessage(), e);
267 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
269 Response errorResp = buildErrorResponse(responseFormat);
270 responseWrapper.setInnerElement(errorResp);
275 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user, ResourceAuthorityTypeEnum resourceAuthority) {
276 log.debug("validate user role");
277 if (resourceAuthority == ResourceAuthorityTypeEnum.NORMATIVE_TYPE_BE) {
278 if (!user.getRole().equals(Role.ADMIN.name())) {
279 log.info("user is not in appropriate role to perform action");
280 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
281 log.debug("audit before sending response");
282 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
284 Response response = buildErrorResponse(responseFormat);
285 errorResponseWrapper.setInnerElement(response);
288 validateUserRole(errorResponseWrapper, user);
293 protected void validateAndFillResourceJson(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, User user, ResourceAuthorityTypeEnum resourceAuthorityEnum, String resourceInfo) {
296 log.debug("The received json is {}", resourceInfo);
297 UploadResourceInfo resourceInfoObject = gson.fromJson(resourceInfo, UploadResourceInfo.class);
298 if (resourceInfoObject == null) {
301 if (!resourceAuthorityEnum.isBackEndImport()) {
302 isValid = resourceInfoObject.getPayloadName() != null && !resourceInfoObject.getPayloadName().isEmpty();
303 //only resource name is checked
307 uploadResourceInfoWrapper.setInnerElement(resourceInfoObject);
310 } catch (JsonSyntaxException e) {
311 log.debug("Invalid json was received. {}", e.getMessage(), e);
316 log.info("Invalid json was received.");
317 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
318 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
319 Response errorResp = buildErrorResponse(responseFormat);
320 responseWrapper.setInnerElement(errorResp);
324 protected void validateAuthorityType(Wrapper<Response> responseWrapper, String authorityType) {
325 log.debug("The received authority type is {}", authorityType);
326 ResourceAuthorityTypeEnum authorityTypeEnum = ResourceAuthorityTypeEnum.findByUrlPath(authorityType);
327 if (authorityTypeEnum == null) {
328 log.info("Invalid authority type was received.");
329 Response errorResp = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
330 responseWrapper.setInnerElement(errorResp);
334 public ServletUtils getServletUtils() {
338 public Gson getGson() {
339 return getServletUtils().getGson();
342 public ComponentsUtils getComponentsUtils() {
343 return getServletUtils().getComponentsUtils();
346 protected void validatePayloadIsTosca(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
347 log.debug("checking payload is valid tosca");
349 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
350 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
352 if (findFirstToscaStringElement.isRight()) {
355 String defenitionVersionFound = findFirstToscaStringElement.left().value();
356 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
359 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
364 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
365 Response errorResponse = buildErrorResponse(responseFormat);
366 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
367 responseWrapper.setInnerElement(errorResponse);
372 protected void validatePayloadIsYml(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaTamplatePayload) {
373 log.debug("checking tosca template is valid yml");
374 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
375 boolean isYamlValid = yamlConvertor.isValidYaml(toscaTamplatePayload.getBytes());
377 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
378 Response errorResponse = buildErrorResponse(responseFormat);
379 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
380 responseWrapper.setInnerElement(errorResponse);
384 protected void validatePayloadNameSpace(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, String toscaPayload) {
386 String nameSpace = "";
387 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
388 Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
389 if (toscaElement.isRight() || toscaElement.left().value().size() != 1) {
392 nameSpace = toscaElement.left().value().keySet().iterator().next();
393 isValid = nameSpace.startsWith(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX);
396 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_NAMESPACE);
397 Response errorResponse = buildErrorResponse(responseFormat);
398 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
399 responseWrapper.setInnerElement(errorResponse);
401 String str1 = nameSpace.substring(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX.length());
402 String[] findTypes = str1.split("\\.");
403 if (ResourceTypeEnum.containsName(findTypes[0].toUpperCase())) {
404 String type = findTypes[0].toUpperCase();
405 resourceInfo.setResourceType(type);
407 resourceInfo.setResourceType(ResourceTypeEnum.VFC.name());
413 protected void validatePayloadIsSingleResource(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
414 log.debug("checking payload contains single resource");
416 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
417 Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
418 if (toscaElement.isRight()) {
421 isValid = toscaElement.left().value().size() == 1;
425 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_SINGLE_RESOURCE);
426 Response errorResponse = buildErrorResponse(responseFormat);
427 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
428 responseWrapper.setInnerElement(errorResponse);
433 protected void validatePayloadIsNotService(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaPayload) {
434 log.debug("checking payload is not a tosca service");
435 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
436 Either<Object, ResultStatusEnum> toscaElement = ImportUtils.findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL);
438 if (toscaElement.isLeft()) {
439 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_RESOURCE_TOSCA_TEMPLATE);
440 Response errorResponse = buildErrorResponse(responseFormat);
441 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
442 responseWrapper.setInnerElement(errorResponse);
447 protected void validateToscaTemplatePayloadName(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
448 String toscaTemplatePayloadName = uploadResourceInfo.getPayloadName();
449 boolean isValidSuffix = false;
450 if (toscaTemplatePayloadName != null && !toscaTemplatePayloadName.isEmpty()) {
451 for (String validSuffix : TOSCA_YML_CSAR_VALID_SUFFIX) {
452 isValidSuffix = isValidSuffix || toscaTemplatePayloadName.toLowerCase().endsWith(validSuffix);
455 if (!isValidSuffix) {
456 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_FILE_EXTENSION);
457 Response errorResponse = buildErrorResponse(responseFormat);
458 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
459 responseWrapper.setInnerElement(errorResponse);
464 protected void validateMD5(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfo, HttpServletRequest request, String resourceInfoJsonString) {
466 String recievedMD5 = request.getHeader(Constants.MD5_HEADER);
467 if (recievedMD5 == null) {
470 String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(resourceInfoJsonString);
471 isValid = calculateMD5.equals(recievedMD5);
474 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_CHECKSUM);
475 Response errorResponse = buildErrorResponse(responseFormat);
476 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
477 responseWrapper.setInnerElement(errorResponse);
481 protected void validateComponentType(Wrapper<Response> responseWrapper, Wrapper<ComponentTypeEnum> componentTypeWrapper, String componentType) {
483 if (componentType == null) {
486 if (ComponentTypeEnum.RESOURCE_PARAM_NAME.equalsIgnoreCase(componentType)) {
488 componentTypeWrapper.setInnerElement(ComponentTypeEnum.RESOURCE);
489 } else if (ComponentTypeEnum.SERVICE_PARAM_NAME.equalsIgnoreCase(componentType)) {
491 componentTypeWrapper.setInnerElement(ComponentTypeEnum.SERVICE);
497 log.debug("Invalid componentType:{}", componentType);
498 responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, componentType)));
502 protected Either<ComponentTypeEnum, ResponseFormat> convertToComponentType(String componentType) {
503 Wrapper<Response> errorWrapper = new Wrapper<>();
504 Wrapper<ComponentTypeEnum> componentWrapper = new Wrapper<>();
505 validateComponentType(errorWrapper, componentWrapper, componentType);
506 return errorWrapper.isEmpty() ? Either.left(componentWrapper.getInnerElement()) : Either.right(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
509 protected void fillToscaTemplateFromJson(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo resourceInfo) {
510 if (resourceInfo.getPayloadData() == null || resourceInfo.getPayloadData().isEmpty()) {
511 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_PAYLOAD);
512 Response errorResponse = buildErrorResponse(responseFormat);
513 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
514 responseWrapper.setInnerElement(errorResponse);
516 String toscaPayload = resourceInfo.getPayloadData();
517 String decodedPayload = new String(Base64.decodeBase64(toscaPayload));
518 yamlStringWrapper.setInnerElement(decodedPayload);
523 protected void fillPayload(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, String resourceInfoJsonString, ResourceAuthorityTypeEnum resourceAuthorityEnum,
524 File file) throws FileNotFoundException {
526 if (responseWrapper.isEmpty()) {
527 if (resourceAuthorityEnum.isBackEndImport()) {
528 // PrePayload Validations
529 if (responseWrapper.isEmpty()) {
530 validateDataNotNull(responseWrapper, file, resourceInfoJsonString);
532 if(!resourceAuthorityEnum.equals(ResourceAuthorityTypeEnum.CSAR_TYPE_BE)){
533 if (responseWrapper.isEmpty()) {
534 validateZip(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
537 // Fill PayLoad From File
538 if (responseWrapper.isEmpty()) {
539 fillToscaTemplateFromZip(yamlStringWrapper, uploadResourceInfoWrapper.getInnerElement().getPayloadName(), file);
543 if (responseWrapper.isEmpty()) {
544 validateCsar(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
547 // Fill PayLoad From File
548 if (responseWrapper.isEmpty()) {
549 fillPayloadDataFromFile(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), file);
555 // Fill PayLoad From JSON
556 if (responseWrapper.isEmpty()) {
557 fillToscaTemplateFromJson(responseWrapper, yamlStringWrapper, user, uploadResourceInfoWrapper.getInnerElement());
565 protected void specificResourceAuthorityValidations(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, HttpServletRequest request, String resourceInfoJsonString,
566 ResourceAuthorityTypeEnum resourceAuthorityEnum) throws FileNotFoundException {
568 if (responseWrapper.isEmpty()) {
569 // UI Only Validation
570 if (!resourceAuthorityEnum.isBackEndImport()) {
571 importUIValidations(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, request, resourceInfoJsonString);
574 // User Defined Type Resources
575 if (resourceAuthorityEnum.isUserTypeResource() && !CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {
576 if (responseWrapper.isEmpty()) {
577 validatePayloadNameSpace(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, yamlStringWrapper.getInnerElement());
584 protected void commonGeneralValidations(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, ResourceAuthorityTypeEnum resourceAuthorityEnum, String userUserId,
585 String resourceInfoJsonString) {
587 if (responseWrapper.isEmpty()) {
588 validateUserExist(responseWrapper, userWrapper, userUserId);
591 if (responseWrapper.isEmpty()) {
592 validateUserRole(responseWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum);
595 if (responseWrapper.isEmpty()) {
596 validateAndFillResourceJson(responseWrapper, uploadResourceInfoWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum, resourceInfoJsonString);
599 if (responseWrapper.isEmpty()) {
600 validateToscaTemplatePayloadName(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
602 if (responseWrapper.isEmpty()) {
603 validateResourceType(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
608 private void validateResourceType(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
609 String resourceType = uploadResourceInfo.getResourceType();
610 if (resourceType == null || !ResourceTypeEnum.containsName(resourceType)) {
611 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
612 Response errorResponse = buildErrorResponse(responseFormat);
613 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
614 responseWrapper.setInnerElement(errorResponse);
618 protected void importUIValidations(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, HttpServletRequest request, String resourceInfoJsonString) {
619 if (responseWrapper.isEmpty()) {
620 validateMD5(responseWrapper, user, resourceInfo, request, resourceInfoJsonString);
622 if (responseWrapper.isEmpty() && request != null && request.getMethod() != null && request.getMethod().equals("POST")) {
623 validateResourceDoesNotExist(responseWrapper, user, resourceInfo.getName());
627 protected void commonPayloadValidations(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo uploadResourceInfo) {
629 if (responseWrapper.isEmpty()) {
630 validatePayloadIsYml(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
632 if (responseWrapper.isEmpty()) {
633 validatePayloadIsTosca(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
635 if (responseWrapper.isEmpty()) {
636 validatePayloadIsNotService(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
638 if (responseWrapper.isEmpty()) {
639 validatePayloadIsSingleResource(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
644 protected void handleImport(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfoObject, String yamlAsString, ResourceAuthorityTypeEnum authority, boolean createNewVersion, String resourceUniqueId) {
645 Either<ImmutablePair<Resource, ActionStatus>, ResponseFormat> createOrUpdateResponse = null;
646 Response response = null;
647 Object representation = null;
648 ImmutablePair<Resource, ActionStatus> importedResourceStatus = null;
649 if (CsarValidationUtils.isCsarPayloadName(resourceInfoObject.getPayloadName())) {
650 log.debug("import resource from csar");
651 importedResourceStatus = importResourceFromUICsar(resourceInfoObject, user, resourceUniqueId);
652 } else if (!authority.isUserTypeResource()) {
653 log.debug("import normative type resource");
654 createOrUpdateResponse = resourceImportManager.importNormativeResource(yamlAsString, resourceInfoObject, user, createNewVersion, true);
656 log.debug("import user resource (not normative type)");
657 createOrUpdateResponse = resourceImportManager.importUserDefinedResource(yamlAsString, resourceInfoObject, user, false);
659 if (createOrUpdateResponse!= null){
660 if(createOrUpdateResponse.isRight()){
661 response = buildErrorResponse(createOrUpdateResponse.right().value());
663 importedResourceStatus = createOrUpdateResponse.left().value();
666 if(importedResourceStatus != null){
668 representation = RepresentationUtils.toRepresentation(importedResourceStatus.left);
669 } catch (IOException e) {
670 log.debug("Error while building resource representation : {}", e.getMessage(), e);
672 response = buildOkResponse(getComponentsUtils().getResponseFormat(importedResourceStatus.right), representation);
674 responseWrapper.setInnerElement(response);
677 private ImmutablePair<Resource, ActionStatus> importResourceFromUICsar(UploadResourceInfo resourceInfoObject, User user, String resourceUniqueId) {
679 Resource newResource;
680 ImmutablePair<Resource, ActionStatus> result = null;
681 ActionStatus actionStatus;
682 Resource resource = new Resource();
683 String payloadName = resourceInfoObject.getPayloadName();
684 fillResourceFromResourceInfoObject(resource, resourceInfoObject);
686 Either<Map<String, byte[]>, ResponseFormat> csarUIPayloadRes = getCsarFromPayload(resourceInfoObject);
687 if (csarUIPayloadRes.isRight()) {
688 throw new ByResponseFormatComponentException(csarUIPayloadRes.right().value());
690 Map<String, byte[]> csarUIPayload = csarUIPayloadRes.left().value();
692 getAndValidateCsarYaml(csarUIPayload, resource, user, payloadName);
694 if (resourceUniqueId == null || resourceUniqueId.isEmpty()) {
695 newResource = resourceImportManager.getResourceBusinessLogic().createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, csarUIPayload, payloadName);
696 actionStatus = ActionStatus.CREATED;
698 newResource = resourceImportManager.getResourceBusinessLogic().validateAndUpdateResourceFromCsar(resource, user, csarUIPayload, payloadName, resourceUniqueId);
699 actionStatus = ActionStatus.OK;
701 return new ImmutablePair<>(newResource, actionStatus);
704 private Resource throwComponentException(ResponseFormat responseFormat) {
705 throw new ByResponseFormatComponentException(responseFormat);
708 private void getAndValidateCsarYaml(Map<String, byte[]> csarUIPayload, Resource resource, User user, String csarUUID) {
710 Either<ImmutablePair<String, String>, ResponseFormat> getToscaYamlRes = CsarValidationUtils.getToscaYaml(csarUIPayload, csarUUID, getComponentsUtils());
712 if (getToscaYamlRes.isRight()) {
713 ResponseFormat responseFormat = getToscaYamlRes.right().value();
714 log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat);
715 BeEcompErrorManager.getInstance().logBeDaoSystemError("Creating resource from CSAR: fetching CSAR with id " + csarUUID + " failed");
716 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.CREATE_RESOURCE);
717 throwComponentException(responseFormat);
719 String toscaYaml = getToscaYamlRes.left().value().getValue();
721 log.debug("checking tosca template is valid yml");
722 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
723 boolean isValid = yamlConvertor.isValidYaml(toscaYaml.getBytes());
725 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
726 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
727 throwComponentException(responseFormat);
730 log.debug("checking payload is valid tosca");
731 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaYaml);
732 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
734 if (findFirstToscaStringElement.isRight()) {
737 String defenitionVersionFound = findFirstToscaStringElement.left().value();
738 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
741 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
746 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
747 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
748 throwComponentException(responseFormat);
752 private void fillResourceFromResourceInfoObject(Resource resource, UploadResourceInfo resourceInfoObject) {
753 resourceImportManager.populateResourceMetadata(resourceInfoObject, resource);
754 fillArtifacts(resource, resourceInfoObject);
758 private void fillArtifacts(Resource resource, UploadResourceInfo resourceInfoObject) {
759 if (resource != null && resourceInfoObject != null) {
760 List<UploadArtifactInfo> artifactList = resourceInfoObject.getArtifactList();
761 if (artifactList != null) {
762 Map<String, ArtifactDefinition> artifactsHM = new HashMap<>();
763 for (UploadArtifactInfo artifact : artifactList) {
764 ArtifactDefinition artifactDef = new ArtifactDefinition();
765 artifactDef.setArtifactName(artifact.getArtifactName());
766 artifactDef.setArtifactType(artifact.getArtifactType().getType());
767 artifactDef.setDescription(artifact.getArtifactDescription());
768 artifactDef.setPayloadData(artifact.getArtifactData());
769 artifactDef.setArtifactRef(artifact.getArtifactPath());
770 artifactsHM.put(artifactDef.getArtifactName(), artifactDef);
772 resource.setArtifacts(artifactsHM);
777 private Either<Map<String, byte[]>, ResponseFormat> getCsarFromPayload(UploadResourceInfo innerElement) {
778 String csarUUID = innerElement.getPayloadName();
779 String payloadData = innerElement.getPayloadData();
780 if (payloadData == null) {
781 log.info("Failed to decode received csar {}", csarUUID);
782 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_NOT_FOUND, csarUUID));
785 byte[] decodedPayload = Base64.decodeBase64(payloadData.getBytes(StandardCharsets.UTF_8));
786 if (decodedPayload == null) {
787 log.info("Failed to decode received csar {}", csarUUID);
788 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_NOT_FOUND, csarUUID));
791 Map<String, byte[]> csar = null;
793 csar = ZipUtils.readZip(decodedPayload, false);
794 } catch (final ZipException e) {
795 log.info("Failed to unzip received csar {}", csarUUID, e);
797 if (MapUtils.isEmpty(csar)) {
798 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID, csarUUID));
800 return Either.left(csar);
803 protected void validateInputStream(final HttpServletRequest request, Wrapper<String> dataWrapper, Wrapper<ResponseFormat> errorWrapper) throws IOException {
804 InputStream inputStream = request.getInputStream();
805 byte[] bytes = IOUtils.toByteArray(inputStream);
806 if (bytes == null || bytes.length == 0) {
807 log.info("Empty body was sent.");
808 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
810 dataWrapper.setInnerElement(new String(bytes, StandardCharsets.UTF_8));
815 protected <T> void validateClassParse(String data, Wrapper<T> parsedClassWrapper, Supplier<Class<T>> classGen, Wrapper<ResponseFormat> errorWrapper) {
817 T parsedClass = gson.fromJson(data, classGen.get());
818 if (parsedClass == null) {
819 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
821 parsedClassWrapper.setInnerElement(parsedClass);
823 } catch (JsonSyntaxException e) {
824 log.debug("Failed to decode received {} {} to object.", classGen.get().getName(), data, e);
825 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
829 protected void validateComponentInstanceBusinessLogic(HttpServletRequest request, String containerComponentType, Wrapper<ComponentInstanceBusinessLogic> blWrapper, Wrapper<ResponseFormat> errorWrapper) {
830 ServletContext context = request.getSession().getServletContext();
831 if (componentInstanceBusinessLogic == null) {
832 log.debug("Unsupported component type {}", containerComponentType);
833 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
835 blWrapper.setInnerElement(componentInstanceBusinessLogic);
839 protected <T> Response buildResponseFromElement(Wrapper<ResponseFormat> errorWrapper, Wrapper<T> attributeWrapper) throws IOException {
841 if (errorWrapper.isEmpty()) {
842 ObjectMapper mapper = new ObjectMapper();
843 String result = mapper.writeValueAsString(attributeWrapper.getInnerElement());
844 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
846 response = buildErrorResponse(errorWrapper.getInnerElement());
851 protected void validateXECOMPInstanceIDHeader(String instanceIdHeader, Wrapper<ResponseFormat> responseWrapper) {
852 ResponseFormat responseFormat;
853 if(StringUtils.isEmpty(instanceIdHeader) ){
854 log.debug("Missing X-ECOMP-InstanceID header");
855 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
856 responseWrapper.setInnerElement(responseFormat);
860 protected void validateHttpCspUserIdHeader(String header, Wrapper<ResponseFormat> responseWrapper) {
861 ResponseFormat responseFormat;
862 if( StringUtils.isEmpty(header)){
863 log.debug("MissingUSER_ID");
864 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_USER_ID);
865 responseWrapper.setInnerElement(responseFormat);
870 * Convert json to Object object
872 * @param classSupplier
876 public <T> Either<T, ResponseFormat> parseToObject(String json, Supplier<Class<T>> classSupplier) {
879 T object = RepresentationUtils.fromRepresentation(json, classSupplier.get());
880 return Either.left(object);
881 } catch (Exception e) {
882 log.debug("Failed to parse json to {} object", classSupplier.get().getName(), e);
883 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
884 return Either.right(responseFormat);
889 * Convert json to Object object
895 public <T> Either<List<T>, ResponseFormat> parseListOfObjects(String json, Type type) {
897 List<T> listOfObjects = gson.fromJson(json, type);
898 return Either.left(listOfObjects);
899 } catch (Exception e) {
900 log.debug("Failed to parse json to {} object", type.getClass().getName(), e);
901 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
902 return Either.right(responseFormat);