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;
29 import org.apache.commons.codec.binary.Base64;
30 import org.apache.commons.collections4.MapUtils;
31 import org.apache.commons.io.IOUtils;
32 import org.apache.commons.lang3.StringUtils;
33 import org.apache.commons.lang3.tuple.ImmutablePair;
34 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
35 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
36 import org.openecomp.sdc.be.components.impl.ImportUtils;
37 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
38 import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
39 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
40 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
41 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
42 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
43 import org.openecomp.sdc.be.config.BeEcompErrorManager;
44 import org.openecomp.sdc.be.dao.api.ActionStatus;
45 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
46 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
47 import org.openecomp.sdc.be.impl.ComponentsUtils;
48 import org.openecomp.sdc.be.impl.ServletUtils;
49 import org.openecomp.sdc.be.model.ArtifactDefinition;
50 import org.openecomp.sdc.be.model.Resource;
51 import org.openecomp.sdc.be.model.UploadResourceInfo;
52 import org.openecomp.sdc.be.model.User;
53 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
54 import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
55 import org.openecomp.sdc.be.user.Role;
56 import org.openecomp.sdc.be.user.UserBusinessLogic;
57 import org.openecomp.sdc.be.utils.TypeUtils;
58 import org.openecomp.sdc.common.api.Constants;
59 import org.openecomp.sdc.common.api.UploadArtifactInfo;
60 import org.openecomp.sdc.common.datastructure.Wrapper;
61 import org.openecomp.sdc.common.log.wrappers.Logger;
62 import org.openecomp.sdc.common.util.GeneralUtility;
63 import org.openecomp.sdc.common.util.YamlToObjectConverter;
64 import org.openecomp.sdc.common.zip.ZipUtils;
65 import org.openecomp.sdc.common.zip.exception.ZipException;
66 import org.openecomp.sdc.exception.ResponseFormat;
67 import org.yaml.snakeyaml.Yaml;
69 import javax.servlet.ServletContext;
70 import javax.servlet.http.HttpServletRequest;
71 import javax.ws.rs.core.Response;
73 import java.io.FileInputStream;
74 import java.io.IOException;
75 import java.io.InputStream;
76 import java.lang.reflect.Type;
77 import java.nio.charset.StandardCharsets;
78 import java.util.Arrays;
79 import java.util.HashMap;
80 import java.util.List;
82 import java.util.function.Supplier;
84 public abstract class AbstractValidationsServlet extends BeGenericServlet {
86 private static final Logger log = Logger.getLogger(AbstractValidationsServlet.class);
87 private static final String TOSCA_SIMPLE_YAML_PREFIX = "tosca_simple_yaml_";
88 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");
89 private static final List<String> TOSCA_YML_CSAR_VALID_SUFFIX = Arrays.asList(".yml", ".yaml", ".csar");
91 protected ServletUtils servletUtils;
92 protected ResourceImportManager resourceImportManager;
93 protected final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
96 public AbstractValidationsServlet(UserBusinessLogic userBusinessLogic,
97 ComponentInstanceBusinessLogic componentInstanceBL, ComponentsUtils componentsUtils,
98 ServletUtils servletUtils, ResourceImportManager resourceImportManager) {
99 super(userBusinessLogic, componentsUtils);
100 this.servletUtils = servletUtils;
101 this.resourceImportManager = resourceImportManager;
102 this.componentInstanceBusinessLogic = componentInstanceBL;
105 protected void init() {
108 protected void validateResourceDoesNotExist(Wrapper<Response> responseWrapper, User user, String resourceName) {
109 if (resourceImportManager.isResourceExist(resourceName)) {
110 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESOURCE_ALREADY_EXISTS);
111 Response errorResponse = buildErrorResponse(responseFormat);
112 getComponentsUtils().auditResource(responseFormat, user, resourceName, AuditingActionEnum.IMPORT_RESOURCE);
113 responseWrapper.setInnerElement(errorResponse);
117 protected void validateUserExist(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, String userUserId) {
118 log.debug("get user {} from DB", userUserId);
120 if (userUserId == null) {
121 log.info("user userId is null");
122 Response response = returnMissingInformation(new User());
123 responseWrapper.setInnerElement(response);
127 UserBusinessLogic userAdmin = getServletUtils().getUserAdmin();
129 User user = userAdmin.getUser(userUserId);
130 userWrapper.setInnerElement(user);
131 } catch (ComponentException ce) {
132 log.info("user is not listed. userId={}", userUserId);
133 User user = new User();
134 user.setUserId(userUserId);
135 Response response = returnMissingInformation(user);
136 responseWrapper.setInnerElement(response);
141 protected Response returnMissingInformation(User user) {
142 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_INFORMATION);
143 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
144 return buildErrorResponse(responseFormat);
147 protected void validateDataNotNull(Wrapper<Response> responseWrapper, Object... dataParams) {
148 for (Object dataElement : dataParams) {
149 if (dataElement == null) {
150 log.info("Invalid body was received.");
151 Response response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
152 responseWrapper.setInnerElement(response);
159 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user) {
160 log.debug("validate user role");
161 if (!user.getRole().equals(Role.ADMIN.name()) && !user.getRole().equals(Role.DESIGNER.name())) {
162 log.info("user is not in appropriate role to perform action");
163 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
164 log.debug("audit before sending response");
165 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
167 Response response = buildErrorResponse(responseFormat);
168 errorResponseWrapper.setInnerElement(response);
173 protected void validateZip(final Wrapper<Response> responseWrapper, final File zipFile, final String payloadName) {
174 if (StringUtils.isEmpty(payloadName)) {
175 log.info("Invalid JSON was received. Payload name is empty");
176 final Response errorResponse =
177 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
178 responseWrapper.setInnerElement(errorResponse);
181 final Map<String, byte[]> unzippedFolder;
183 unzippedFolder = ZipUtils.readZip(zipFile, false);
184 } catch (final ZipException e) {
185 log.error("Could not read ZIP file '{}' for validation", zipFile.getName(), e);
186 final Response errorResponse =
187 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
188 responseWrapper.setInnerElement(errorResponse);
191 if (!unzippedFolder.containsKey(payloadName)) {
192 log.info("Could no find payload '{}' in ZIP file '{}'", payloadName, zipFile.getName());
193 final Response errorResponse =
194 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
195 responseWrapper.setInnerElement(errorResponse);
201 protected void validateCsar(final Wrapper<Response> responseWrapper, final File csarFile, final String payloadName) {
202 if (StringUtils.isEmpty(payloadName)) {
203 log.info("Invalid JSON was received. Payload name is empty");
204 Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
205 responseWrapper.setInnerElement(errorResponse);
208 final Map<String, byte[]> unzippedFolder;
210 unzippedFolder = ZipUtils.readZip(csarFile, false);
211 } catch (final ZipException e) {
212 log.error("Could not read CSAR file '{}' for validation", csarFile.getName(), e);
213 final Response errorResponse =
214 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
215 responseWrapper.setInnerElement(errorResponse);
218 if (unzippedFolder.isEmpty()) {
219 log.info("The CSAR file is empty");
220 Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
221 responseWrapper.setInnerElement(errorResponse);
226 protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
227 extractZipContents(yamlStringWrapper, file);
230 public static void extractZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
231 final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
232 String ymlName = unzippedFolder.keySet().iterator().next();
233 fillToscaTemplateFromZip(yamlStringWrapper, ymlName, file);
236 private static void fillToscaTemplateFromZip(final Wrapper<String> yamlStringWrapper, final String payloadName,
237 final File file) throws ZipException {
238 final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
239 final byte[] yamlFileInBytes = unzippedFolder.get(payloadName);
240 final String yamlAsString = new String(yamlFileInBytes, StandardCharsets.UTF_8);
241 log.debug("received yaml: {}", yamlAsString);
242 yamlStringWrapper.setInnerElement(yamlAsString);
245 protected void fillPayloadDataFromFile(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfoWrapper, File file) {
246 try(InputStream fileInputStream = new FileInputStream(file)){
248 byte [] data = new byte[(int)file.length()];
249 if( fileInputStream.read(data) == -1){
250 log.info("Invalid json was received.");
251 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
253 Response errorResp = buildErrorResponse(responseFormat);
254 responseWrapper.setInnerElement(errorResp);
256 String payloadData = Base64.encodeBase64String(data);
257 uploadResourceInfoWrapper.setPayloadData(payloadData);
261 } catch (IOException e) {
262 log.info("Invalid json was received or Error while closing input Stream.");
263 log.debug("Invalid json was received or Error while closing input Stream. {}", e.getMessage(), e);
264 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
266 Response errorResp = buildErrorResponse(responseFormat);
267 responseWrapper.setInnerElement(errorResp);
272 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user, ResourceAuthorityTypeEnum resourceAuthority) {
273 log.debug("validate user role");
274 if (resourceAuthority == ResourceAuthorityTypeEnum.NORMATIVE_TYPE_BE) {
275 if (!user.getRole().equals(Role.ADMIN.name())) {
276 log.info("user is not in appropriate role to perform action");
277 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
278 log.debug("audit before sending response");
279 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
281 Response response = buildErrorResponse(responseFormat);
282 errorResponseWrapper.setInnerElement(response);
285 validateUserRole(errorResponseWrapper, user);
290 protected void validateAndFillResourceJson(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, User user, ResourceAuthorityTypeEnum resourceAuthorityEnum, String resourceInfo) {
293 log.debug("The received json is {}", resourceInfo);
294 UploadResourceInfo resourceInfoObject = gson.fromJson(resourceInfo, UploadResourceInfo.class);
295 if (resourceInfoObject == null) {
298 if (!resourceAuthorityEnum.isBackEndImport()) {
299 isValid = resourceInfoObject.getPayloadName() != null && !resourceInfoObject.getPayloadName().isEmpty();
300 //only resource name is checked
304 uploadResourceInfoWrapper.setInnerElement(resourceInfoObject);
307 } catch (JsonSyntaxException e) {
308 log.debug("Invalid json was received. {}", e.getMessage(), e);
313 log.info("Invalid json was received.");
314 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
315 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
316 Response errorResp = buildErrorResponse(responseFormat);
317 responseWrapper.setInnerElement(errorResp);
321 protected void validateAuthorityType(Wrapper<Response> responseWrapper, String authorityType) {
322 log.debug("The received authority type is {}", authorityType);
323 ResourceAuthorityTypeEnum authorityTypeEnum = ResourceAuthorityTypeEnum.findByUrlPath(authorityType);
324 if (authorityTypeEnum == null) {
325 log.info("Invalid authority type was received.");
326 Response errorResp = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
327 responseWrapper.setInnerElement(errorResp);
331 public ServletUtils getServletUtils() {
335 public Gson getGson() {
336 return getServletUtils().getGson();
339 public ComponentsUtils getComponentsUtils() {
340 return getServletUtils().getComponentsUtils();
343 protected void validatePayloadIsTosca(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
344 log.debug("checking payload is valid tosca");
346 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
347 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
349 if (findFirstToscaStringElement.isRight()) {
352 String defenitionVersionFound = findFirstToscaStringElement.left().value();
353 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
356 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
361 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
362 Response errorResponse = buildErrorResponse(responseFormat);
363 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
364 responseWrapper.setInnerElement(errorResponse);
369 protected void validatePayloadIsYml(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaTamplatePayload) {
370 log.debug("checking tosca template is valid yml");
371 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
372 boolean isYamlValid = yamlConvertor.isValidYaml(toscaTamplatePayload.getBytes());
374 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
375 Response errorResponse = buildErrorResponse(responseFormat);
376 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
377 responseWrapper.setInnerElement(errorResponse);
381 protected void validatePayloadNameSpace(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, String toscaPayload) {
383 String nameSpace = "";
384 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
385 Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
386 if (toscaElement.isRight() || toscaElement.left().value().size() != 1) {
389 nameSpace = toscaElement.left().value().keySet().iterator().next();
390 isValid = nameSpace.startsWith(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX);
393 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_NAMESPACE);
394 Response errorResponse = buildErrorResponse(responseFormat);
395 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
396 responseWrapper.setInnerElement(errorResponse);
398 String str1 = nameSpace.substring(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX.length());
399 String[] findTypes = str1.split("\\.");
400 if (ResourceTypeEnum.containsName(findTypes[0].toUpperCase())) {
401 String type = findTypes[0].toUpperCase();
402 resourceInfo.setResourceType(type);
404 resourceInfo.setResourceType(ResourceTypeEnum.VFC.name());
410 private void validatePayloadIsSingleResource(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
411 log.debug("checking payload contains single resource");
413 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
414 Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
415 if (toscaElement.isRight()) {
418 isValid = toscaElement.left().value().size() == 1;
422 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_SINGLE_RESOURCE);
423 Response errorResponse = buildErrorResponse(responseFormat);
424 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
425 responseWrapper.setInnerElement(errorResponse);
430 private void validatePayloadIsNotService(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaPayload) {
431 log.debug("checking payload is not a tosca service");
432 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
433 Either<Object, ResultStatusEnum> toscaElement = ImportUtils.findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL);
435 if (toscaElement.isLeft()) {
436 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_RESOURCE_TOSCA_TEMPLATE);
437 Response errorResponse = buildErrorResponse(responseFormat);
438 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
439 responseWrapper.setInnerElement(errorResponse);
444 private void validateToscaTemplatePayloadName(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
445 String toscaTemplatePayloadName = uploadResourceInfo.getPayloadName();
446 boolean isValidSuffix = false;
447 if (toscaTemplatePayloadName != null && !toscaTemplatePayloadName.isEmpty()) {
448 for (String validSuffix : TOSCA_YML_CSAR_VALID_SUFFIX) {
449 isValidSuffix = isValidSuffix || toscaTemplatePayloadName.toLowerCase().endsWith(validSuffix);
452 if (!isValidSuffix) {
453 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_FILE_EXTENSION);
454 Response errorResponse = buildErrorResponse(responseFormat);
455 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
456 responseWrapper.setInnerElement(errorResponse);
461 private void validateMD5(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfo, HttpServletRequest request, String resourceInfoJsonString) {
463 String recievedMD5 = request.getHeader(Constants.MD5_HEADER);
464 if (recievedMD5 == null) {
467 String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(resourceInfoJsonString);
468 isValid = calculateMD5.equals(recievedMD5);
471 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_CHECKSUM);
472 Response errorResponse = buildErrorResponse(responseFormat);
473 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
474 responseWrapper.setInnerElement(errorResponse);
478 ComponentTypeEnum validateComponentType(String componentType) {
479 if (componentType == null) {
480 throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR);
482 if (ComponentTypeEnum.RESOURCE_PARAM_NAME.equalsIgnoreCase(componentType)) {
483 return ComponentTypeEnum.RESOURCE;
485 if (ComponentTypeEnum.SERVICE_PARAM_NAME.equalsIgnoreCase(componentType)) {
486 return ComponentTypeEnum.SERVICE;
488 log.debug("Invalid componentType:{}", componentType);
489 throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR, componentType);
493 ComponentTypeEnum convertToComponentType(String componentType) {
494 return validateComponentType(componentType);
497 private void fillToscaTemplateFromJson(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo resourceInfo) {
498 if (resourceInfo.getPayloadData() == null || resourceInfo.getPayloadData().isEmpty()) {
499 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_PAYLOAD);
500 Response errorResponse = buildErrorResponse(responseFormat);
501 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
502 responseWrapper.setInnerElement(errorResponse);
504 String toscaPayload = resourceInfo.getPayloadData();
505 String decodedPayload = new String(Base64.decodeBase64(toscaPayload));
506 yamlStringWrapper.setInnerElement(decodedPayload);
511 void fillPayload(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, String resourceInfoJsonString, ResourceAuthorityTypeEnum resourceAuthorityEnum,
512 File file) throws ZipException {
514 if (responseWrapper.isEmpty()) {
515 if (resourceAuthorityEnum.isBackEndImport()) {
516 // PrePayload Validations
517 if (responseWrapper.isEmpty()) {
518 validateDataNotNull(responseWrapper, file, resourceInfoJsonString);
520 if(!resourceAuthorityEnum.equals(ResourceAuthorityTypeEnum.CSAR_TYPE_BE)){
521 if (responseWrapper.isEmpty()) {
522 validateZip(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
525 // Fill PayLoad From File
526 if (responseWrapper.isEmpty()) {
527 fillToscaTemplateFromZip(yamlStringWrapper, uploadResourceInfoWrapper.getInnerElement().getPayloadName(), file);
531 if (responseWrapper.isEmpty()) {
532 validateCsar(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
535 // Fill PayLoad From File
536 if (responseWrapper.isEmpty()) {
537 fillPayloadDataFromFile(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), file);
543 // Fill PayLoad From JSON
544 if (responseWrapper.isEmpty()) {
545 fillToscaTemplateFromJson(responseWrapper, yamlStringWrapper, user, uploadResourceInfoWrapper.getInnerElement());
553 protected void specificResourceAuthorityValidations(final Wrapper<Response> responseWrapper,
554 final Wrapper<UploadResourceInfo> uploadResourceInfoWrapper,
555 final Wrapper<String> yamlStringWrapper, final User user,
556 final HttpServletRequest request, final String resourceInfoJsonString,
557 final ResourceAuthorityTypeEnum resourceAuthorityEnum) {
559 if (responseWrapper.isEmpty()) {
560 // UI Only Validation
561 if (!resourceAuthorityEnum.isBackEndImport()) {
562 importUIValidations(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, request, resourceInfoJsonString);
565 // User Defined Type Resources
566 if (resourceAuthorityEnum.isUserTypeResource() && !CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {
567 if (responseWrapper.isEmpty()) {
568 validatePayloadNameSpace(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, yamlStringWrapper.getInnerElement());
575 void commonGeneralValidations(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, ResourceAuthorityTypeEnum resourceAuthorityEnum, String userId,
576 String resourceInfoJsonString) {
578 if (responseWrapper.isEmpty()) {
579 validateUserExist(responseWrapper, userWrapper, userId);
582 if (responseWrapper.isEmpty()) {
583 validateUserRole(responseWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum);
586 if (responseWrapper.isEmpty()) {
587 validateAndFillResourceJson(responseWrapper, uploadResourceInfoWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum, resourceInfoJsonString);
590 if (responseWrapper.isEmpty()) {
591 validateToscaTemplatePayloadName(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
593 if (responseWrapper.isEmpty()) {
594 validateResourceType(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
599 private void validateResourceType(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
600 String resourceType = uploadResourceInfo.getResourceType();
601 if (resourceType == null || !ResourceTypeEnum.containsName(resourceType)) {
602 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
603 Response errorResponse = buildErrorResponse(responseFormat);
604 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
605 responseWrapper.setInnerElement(errorResponse);
609 private void importUIValidations(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, HttpServletRequest request, String resourceInfoJsonString) {
610 if (responseWrapper.isEmpty()) {
611 validateMD5(responseWrapper, user, resourceInfo, request, resourceInfoJsonString);
613 if (responseWrapper.isEmpty() && request != null && request.getMethod() != null && request.getMethod().equals("POST")) {
614 validateResourceDoesNotExist(responseWrapper, user, resourceInfo.getName());
618 void commonPayloadValidations(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo uploadResourceInfo) {
620 if (responseWrapper.isEmpty()) {
621 validatePayloadIsYml(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
623 if (responseWrapper.isEmpty()) {
624 validatePayloadIsTosca(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
626 if (responseWrapper.isEmpty()) {
627 validatePayloadIsNotService(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
629 if (responseWrapper.isEmpty()) {
630 validatePayloadIsSingleResource(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
635 void handleImport(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfoObject, String yamlAsString, ResourceAuthorityTypeEnum authority, boolean createNewVersion, String resourceUniqueId) {
636 ImmutablePair<Resource, ActionStatus> createOrUpdateResponse = null;
637 Response response = null;
638 Object representation = null;
639 ImmutablePair<Resource, ActionStatus> importedResourceStatus = null;
640 if (CsarValidationUtils.isCsarPayloadName(resourceInfoObject.getPayloadName())) {
641 log.debug("import resource from csar");
642 importedResourceStatus = importResourceFromUICsar(resourceInfoObject, user, resourceUniqueId);
643 } else if (!authority.isUserTypeResource()) {
644 log.debug("import normative type resource");
645 createOrUpdateResponse = resourceImportManager.importNormativeResource(yamlAsString, resourceInfoObject, user, createNewVersion, true);
647 log.debug("import user resource (not normative type)");
648 createOrUpdateResponse = resourceImportManager.importUserDefinedResource(yamlAsString, resourceInfoObject, user, false);
650 if (createOrUpdateResponse!= null){
651 importedResourceStatus = createOrUpdateResponse;
653 if(importedResourceStatus != null){
655 representation = RepresentationUtils.toRepresentation(importedResourceStatus.left);
656 } catch (IOException e) {
657 log.debug("Error while building resource representation : {}", e.getMessage(), e);
659 response = buildOkResponse(getComponentsUtils().getResponseFormat(importedResourceStatus.right), representation);
661 responseWrapper.setInnerElement(response);
664 private ImmutablePair<Resource, ActionStatus> importResourceFromUICsar(UploadResourceInfo resourceInfoObject, User user, String resourceUniqueId) {
666 Resource newResource;
667 ActionStatus actionStatus;
668 Resource resource = new Resource();
669 String payloadName = resourceInfoObject.getPayloadName();
670 fillResourceFromResourceInfoObject(resource, resourceInfoObject);
672 Map<String, byte[]> csarUIPayload = getCsarFromPayload(resourceInfoObject);
673 getAndValidateCsarYaml(csarUIPayload, resource, user, payloadName);
675 if (resourceUniqueId == null || resourceUniqueId.isEmpty()) {
676 newResource = resourceImportManager.getResourceBusinessLogic().createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, csarUIPayload, payloadName);
677 actionStatus = ActionStatus.CREATED;
679 newResource = resourceImportManager.getResourceBusinessLogic().validateAndUpdateResourceFromCsar(resource, user, csarUIPayload, payloadName, resourceUniqueId);
680 actionStatus = ActionStatus.OK;
682 return new ImmutablePair<>(newResource, actionStatus);
685 private Resource throwComponentException(ResponseFormat responseFormat) {
686 throw new ByResponseFormatComponentException(responseFormat);
689 private void getAndValidateCsarYaml(Map<String, byte[]> csarUIPayload, Resource resource, User user, String csarUUID) {
691 Either<ImmutablePair<String, String>, ResponseFormat> getToscaYamlRes = CsarValidationUtils.getToscaYaml(csarUIPayload, csarUUID, getComponentsUtils());
693 if (getToscaYamlRes.isRight()) {
694 ResponseFormat responseFormat = getToscaYamlRes.right().value();
695 log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat);
696 BeEcompErrorManager.getInstance().logBeDaoSystemError("Creating resource from CSAR: fetching CSAR with id " + csarUUID + " failed");
697 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.CREATE_RESOURCE);
698 throwComponentException(responseFormat);
700 String toscaYaml = getToscaYamlRes.left().value().getValue();
702 log.debug("checking tosca template is valid yml");
703 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
704 boolean isValid = yamlConvertor.isValidYaml(toscaYaml.getBytes());
706 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
707 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
708 throwComponentException(responseFormat);
711 log.debug("checking payload is valid tosca");
712 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaYaml);
713 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
715 if (findFirstToscaStringElement.isRight()) {
718 String defenitionVersionFound = findFirstToscaStringElement.left().value();
719 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
722 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
727 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
728 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
729 throwComponentException(responseFormat);
733 private void fillResourceFromResourceInfoObject(Resource resource, UploadResourceInfo resourceInfoObject) {
734 resourceImportManager.populateResourceMetadata(resourceInfoObject, resource);
735 fillArtifacts(resource, resourceInfoObject);
739 private void fillArtifacts(Resource resource, UploadResourceInfo resourceInfoObject) {
740 if (resource != null && resourceInfoObject != null) {
741 List<UploadArtifactInfo> artifactList = resourceInfoObject.getArtifactList();
742 if (artifactList != null) {
743 Map<String, ArtifactDefinition> artifactsHM = new HashMap<>();
744 for (UploadArtifactInfo artifact : artifactList) {
745 ArtifactDefinition artifactDef = new ArtifactDefinition();
746 artifactDef.setArtifactName(artifact.getArtifactName());
747 artifactDef.setArtifactType(artifact.getArtifactType().getType());
748 artifactDef.setDescription(artifact.getArtifactDescription());
749 artifactDef.setPayloadData(artifact.getArtifactData());
750 artifactDef.setArtifactRef(artifact.getArtifactPath());
751 artifactsHM.put(artifactDef.getArtifactName(), artifactDef);
753 resource.setArtifacts(artifactsHM);
758 private Map<String, byte[]> getCsarFromPayload(UploadResourceInfo innerElement) {
759 String csarUUID = innerElement.getPayloadName();
760 String payloadData = innerElement.getPayloadData();
761 if (payloadData == null) {
762 log.info("Failed to decode received csar {}", csarUUID);
763 throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
766 byte[] decodedPayload = Base64.decodeBase64(payloadData.getBytes(StandardCharsets.UTF_8));
767 if (decodedPayload == null) {
768 log.info("Failed to decode received csar {}", csarUUID);
769 throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
772 Map<String, byte[]> csar = null;
774 csar = ZipUtils.readZip(decodedPayload, false);
775 } catch (final ZipException e) {
776 log.info("Failed to unzip received csar {}", csarUUID, e);
778 if (MapUtils.isEmpty(csar)) {
783 void validateInputStream(final HttpServletRequest request, Wrapper<String> dataWrapper, Wrapper<ResponseFormat> errorWrapper) throws IOException {
784 InputStream inputStream = request.getInputStream();
785 byte[] bytes = IOUtils.toByteArray(inputStream);
786 if (bytes == null || bytes.length == 0) {
787 log.info("Empty body was sent.");
788 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
790 dataWrapper.setInnerElement(new String(bytes, StandardCharsets.UTF_8));
795 <T> void validateClassParse(String data, Wrapper<T> parsedClassWrapper, Supplier<Class<T>> classGen, Wrapper<ResponseFormat> errorWrapper) {
797 T parsedClass = gson.fromJson(data, classGen.get());
798 if (parsedClass == null) {
799 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
801 parsedClassWrapper.setInnerElement(parsedClass);
803 } catch (JsonSyntaxException e) {
804 log.debug("Failed to decode received {} {} to object.", classGen.get().getName(), data, e);
805 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
809 void validateComponentInstanceBusinessLogic(HttpServletRequest request, String containerComponentType, Wrapper<ComponentInstanceBusinessLogic> blWrapper, Wrapper<ResponseFormat> errorWrapper) {
810 ServletContext context = request.getSession().getServletContext();
811 ComponentInstanceBusinessLogic componentInstanceLogic = getComponentInstanceBL(context);
812 if (componentInstanceLogic == null) {
813 log.debug("Unsupported component type {}", containerComponentType);
814 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
816 blWrapper.setInnerElement(componentInstanceLogic);
820 <T> Response buildResponseFromElement(Wrapper<ResponseFormat> errorWrapper, Wrapper<T> attributeWrapper) throws IOException {
822 if (errorWrapper.isEmpty()) {
823 ObjectMapper mapper = new ObjectMapper();
824 String result = mapper.writeValueAsString(attributeWrapper.getInnerElement());
825 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
827 response = buildErrorResponse(errorWrapper.getInnerElement());
832 protected void validateXECOMPInstanceIDHeader(String instanceIdHeader, Wrapper<ResponseFormat> responseWrapper) {
833 ResponseFormat responseFormat;
834 if(StringUtils.isEmpty(instanceIdHeader) ){
835 log.debug("Missing X-ECOMP-InstanceID header");
836 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
837 responseWrapper.setInnerElement(responseFormat);
841 protected void validateHttpCspUserIdHeader(String header, Wrapper<ResponseFormat> responseWrapper) {
842 ResponseFormat responseFormat;
843 if( StringUtils.isEmpty(header)){
844 log.debug("MissingUSER_ID");
845 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_USER_ID);
846 responseWrapper.setInnerElement(responseFormat);
850 <T> Either<T, ResponseFormat> parseToObject(String json, Supplier<Class<T>> classSupplier) {
853 T object = RepresentationUtils.fromRepresentation(json, classSupplier.get());
854 return Either.left(object);
855 } catch (Exception e) {
856 log.debug("Failed to parse json to {} object", classSupplier.get().getName(), e);
857 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
858 return Either.right(responseFormat);
862 public <T> Either<List<T>, ResponseFormat> parseListOfObjects(String json, Type type) {
864 List<T> listOfObjects = gson.fromJson(json, type);
865 return Either.left(listOfObjects);
866 } catch (Exception e) {
867 log.debug("Failed to parse json to {} object", type.getClass().getName(), e);
868 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
869 return Either.right(responseFormat);
872 protected void validateNotEmptyBody(String data) {
873 if (StringUtils.isEmpty(data)) {
874 throw new ByActionStatusComponentException(ActionStatus.MISSING_BODY);