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 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;
71 import javax.servlet.ServletContext;
72 import javax.servlet.http.HttpServletRequest;
73 import javax.ws.rs.core.Response;
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;
84 import java.util.function.Supplier;
86 public abstract class AbstractValidationsServlet extends BeGenericServlet {
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(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");
91 private static final List<String> TOSCA_YML_CSAR_VALID_SUFFIX = Arrays.asList(".yml", ".yaml", ".csar");
93 protected ServletUtils servletUtils;
94 protected ResourceImportManager resourceImportManager;
95 protected final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
98 public AbstractValidationsServlet(UserBusinessLogic userBusinessLogic,
99 ComponentInstanceBusinessLogic componentInstanceBL, ComponentsUtils componentsUtils,
100 ServletUtils servletUtils, ResourceImportManager resourceImportManager) {
101 super(userBusinessLogic, componentsUtils);
102 this.servletUtils = servletUtils;
103 this.resourceImportManager = resourceImportManager;
104 this.componentInstanceBusinessLogic = componentInstanceBL;
107 protected void init() {
110 protected void validateResourceDoesNotExist(Wrapper<Response> responseWrapper, User user, String resourceName) {
111 if (resourceImportManager.isResourceExist(resourceName)) {
112 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESOURCE_ALREADY_EXISTS);
113 Response errorResponse = buildErrorResponse(responseFormat);
114 getComponentsUtils().auditResource(responseFormat, user, resourceName, AuditingActionEnum.IMPORT_RESOURCE);
115 responseWrapper.setInnerElement(errorResponse);
119 protected void validateUserExist(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, String userUserId) {
120 log.debug("get user {} from DB", userUserId);
122 if (userUserId == null) {
123 log.info("user userId is null");
124 Response response = returnMissingInformation(new User());
125 responseWrapper.setInnerElement(response);
129 UserBusinessLogic userAdmin = getServletUtils().getUserAdmin();
131 User user = userAdmin.getUser(userUserId);
132 userWrapper.setInnerElement(user);
133 } catch (ComponentException ce) {
134 log.info("user is not listed. userId={}", userUserId);
135 User user = new User();
136 user.setUserId(userUserId);
137 Response response = returnMissingInformation(user);
138 responseWrapper.setInnerElement(response);
143 protected Response returnMissingInformation(User user) {
144 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_INFORMATION);
145 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
146 return buildErrorResponse(responseFormat);
149 protected void validateDataNotNull(Wrapper<Response> responseWrapper, Object... dataParams) {
150 for (Object dataElement : dataParams) {
151 if (dataElement == null) {
152 log.info("Invalid body was received.");
153 Response response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
154 responseWrapper.setInnerElement(response);
161 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user) {
162 log.debug("validate user role");
163 if (!user.getRole().equals(Role.ADMIN.name()) && !user.getRole().equals(Role.DESIGNER.name())) {
164 log.info("user is not in appropriate role to perform action");
165 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
166 log.debug("audit before sending response");
167 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
169 Response response = buildErrorResponse(responseFormat);
170 errorResponseWrapper.setInnerElement(response);
175 protected void validateZip(final Wrapper<Response> responseWrapper, final File zipFile, final String payloadName) {
176 if (StringUtils.isEmpty(payloadName)) {
177 log.info("Invalid JSON was received. Payload name is empty");
178 final Response errorResponse =
179 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
180 responseWrapper.setInnerElement(errorResponse);
183 final Map<String, byte[]> unzippedFolder;
185 unzippedFolder = ZipUtils.readZip(zipFile, false);
186 } catch (final ZipException e) {
187 log.error("Could not read ZIP file '{}' for validation", zipFile.getName(), e);
188 final Response errorResponse =
189 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
190 responseWrapper.setInnerElement(errorResponse);
193 if (!unzippedFolder.containsKey(payloadName)) {
194 log.info("Could no find payload '{}' in ZIP file '{}'", payloadName, zipFile.getName());
195 final Response errorResponse =
196 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
197 responseWrapper.setInnerElement(errorResponse);
203 protected void validateCsar(final Wrapper<Response> responseWrapper, final File csarFile, final String payloadName) {
204 if (StringUtils.isEmpty(payloadName)) {
205 log.info("Invalid JSON was received. Payload name is empty");
206 Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
207 responseWrapper.setInnerElement(errorResponse);
210 final Map<String, byte[]> unzippedFolder;
212 unzippedFolder = ZipUtils.readZip(csarFile, false);
213 } catch (final ZipException e) {
214 log.error("Could not read CSAR file '{}' for validation", csarFile.getName(), e);
215 final Response errorResponse =
216 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
217 responseWrapper.setInnerElement(errorResponse);
220 if (unzippedFolder.isEmpty()) {
221 log.info("The CSAR file is empty");
222 Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
223 responseWrapper.setInnerElement(errorResponse);
228 protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
229 extractZipContents(yamlStringWrapper, file);
232 public static void extractZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
233 final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
234 String ymlName = unzippedFolder.keySet().iterator().next();
235 fillToscaTemplateFromZip(yamlStringWrapper, ymlName, file);
238 private static void fillToscaTemplateFromZip(final Wrapper<String> yamlStringWrapper, final String payloadName,
239 final File file) throws ZipException {
240 final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
241 final byte[] yamlFileInBytes = unzippedFolder.get(payloadName);
242 final String yamlAsString = new String(yamlFileInBytes, StandardCharsets.UTF_8);
243 log.debug("received yaml: {}", yamlAsString);
244 yamlStringWrapper.setInnerElement(yamlAsString);
247 protected void fillPayloadDataFromFile(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfoWrapper, File file) {
248 try(InputStream fileInputStream = new FileInputStream(file)){
250 byte [] data = new byte[(int)file.length()];
251 if( fileInputStream.read(data) == -1){
252 log.info("Invalid json was received.");
253 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
255 Response errorResp = buildErrorResponse(responseFormat);
256 responseWrapper.setInnerElement(errorResp);
258 String payloadData = Base64.encodeBase64String(data);
259 uploadResourceInfoWrapper.setPayloadData(payloadData);
263 } catch (IOException e) {
264 log.info("Invalid json was received or Error while closing input Stream.");
265 log.debug("Invalid json was received or Error while closing input Stream. {}", e.getMessage(), e);
266 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
268 Response errorResp = buildErrorResponse(responseFormat);
269 responseWrapper.setInnerElement(errorResp);
274 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user, ResourceAuthorityTypeEnum resourceAuthority) {
275 log.debug("validate user role");
276 if (resourceAuthority == ResourceAuthorityTypeEnum.NORMATIVE_TYPE_BE) {
277 if (!user.getRole().equals(Role.ADMIN.name())) {
278 log.info("user is not in appropriate role to perform action");
279 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
280 log.debug("audit before sending response");
281 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
283 Response response = buildErrorResponse(responseFormat);
284 errorResponseWrapper.setInnerElement(response);
287 validateUserRole(errorResponseWrapper, user);
292 protected void validateAndFillResourceJson(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, User user, ResourceAuthorityTypeEnum resourceAuthorityEnum, String resourceInfo) {
295 log.debug("The received json is {}", resourceInfo);
296 UploadResourceInfo resourceInfoObject = gson.fromJson(resourceInfo, UploadResourceInfo.class);
297 if (resourceInfoObject == null) {
300 if (!resourceAuthorityEnum.isBackEndImport()) {
301 isValid = resourceInfoObject.getPayloadName() != null && !resourceInfoObject.getPayloadName().isEmpty();
302 //only resource name is checked
306 uploadResourceInfoWrapper.setInnerElement(resourceInfoObject);
309 } catch (JsonSyntaxException e) {
310 log.debug("Invalid json was received. {}", e.getMessage(), e);
315 log.info("Invalid json was received.");
316 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
317 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
318 Response errorResp = buildErrorResponse(responseFormat);
319 responseWrapper.setInnerElement(errorResp);
323 protected void validateAuthorityType(Wrapper<Response> responseWrapper, String authorityType) {
324 log.debug("The received authority type is {}", authorityType);
325 ResourceAuthorityTypeEnum authorityTypeEnum = ResourceAuthorityTypeEnum.findByUrlPath(authorityType);
326 if (authorityTypeEnum == null) {
327 log.info("Invalid authority type was received.");
328 Response errorResp = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
329 responseWrapper.setInnerElement(errorResp);
333 public ServletUtils getServletUtils() {
337 public Gson getGson() {
338 return getServletUtils().getGson();
341 public ComponentsUtils getComponentsUtils() {
342 return getServletUtils().getComponentsUtils();
345 protected void validatePayloadIsTosca(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
346 log.debug("checking payload is valid tosca");
348 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
349 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
351 if (findFirstToscaStringElement.isRight()) {
354 String defenitionVersionFound = findFirstToscaStringElement.left().value();
355 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
358 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
363 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
364 Response errorResponse = buildErrorResponse(responseFormat);
365 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
366 responseWrapper.setInnerElement(errorResponse);
371 protected void validatePayloadIsYml(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaTamplatePayload) {
372 log.debug("checking tosca template is valid yml");
373 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
374 boolean isYamlValid = yamlConvertor.isValidYaml(toscaTamplatePayload.getBytes());
376 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
377 Response errorResponse = buildErrorResponse(responseFormat);
378 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
379 responseWrapper.setInnerElement(errorResponse);
384 * Gets the Resource type from the given node type name.
386 * @param nodeTypeFullName - Node type Name
387 * @return Resource Type name
389 private String getResourceType(final String nodeTypeFullName) {
391 final Optional<String> nodeTypeNamePrefix = getNodeTypeNamePrefix(nodeTypeFullName);
392 if (nodeTypeNamePrefix.isPresent()) {
393 final String nameWithouNamespacePrefix = nodeTypeFullName.substring(nodeTypeNamePrefix.get().length());
394 final String[] findTypes = nameWithouNamespacePrefix.split("\\.");
395 if (findTypes.length > 0) {
396 final ResourceTypeEnum resourceType = ResourceTypeEnum.getType(findTypes[0].toUpperCase());
397 if (resourceType != null) {
398 return resourceType.name();
402 return ResourceTypeEnum.VFC.name();
406 * Extracts the Node Type Name prefix from the given Node Type Name.
407 * @param nodeName - Node Type Name
408 * @return Node Type Name prefix
410 private Optional<String> getNodeTypeNamePrefix(final String nodeName) {
411 final List<String> definedNodeTypeNamespaceList = ConfigurationManager.getConfigurationManager()
412 .getConfiguration().getDefinedResourceNamespace();
413 for (final String validNamespace : definedNodeTypeNamespaceList) {
414 if (nodeName.startsWith(validNamespace)) {
415 return Optional.of(validNamespace);
418 return Optional.empty();
421 protected void validatePayloadNameSpace(final Wrapper<Response> responseWrapper,
422 final UploadResourceInfo resourceInfo,
423 final User user, final String toscaPayload) {
425 String namespace = "";
426 final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
427 final Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
428 if (toscaElement.isRight() || toscaElement.left().value().size() != 1) {
431 namespace = toscaElement.left().value().keySet().iterator().next();
432 isValid = getNodeTypeNamePrefix(namespace).isPresent();
435 final ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_NAMESPACE);
436 final Response errorResponse = buildErrorResponse(responseFormat);
437 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
438 responseWrapper.setInnerElement(errorResponse);
440 resourceInfo.setResourceType(getResourceType(namespace));
444 private void validatePayloadIsSingleResource(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
445 log.debug("checking payload contains single resource");
447 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
448 Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
449 if (toscaElement.isRight()) {
452 isValid = toscaElement.left().value().size() == 1;
456 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_SINGLE_RESOURCE);
457 Response errorResponse = buildErrorResponse(responseFormat);
458 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
459 responseWrapper.setInnerElement(errorResponse);
464 private void validatePayloadIsNotService(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaPayload) {
465 log.debug("checking payload is not a tosca service");
466 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
467 Either<Object, ResultStatusEnum> toscaElement = ImportUtils.findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL);
469 if (toscaElement.isLeft()) {
470 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_RESOURCE_TOSCA_TEMPLATE);
471 Response errorResponse = buildErrorResponse(responseFormat);
472 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
473 responseWrapper.setInnerElement(errorResponse);
478 private void validateToscaTemplatePayloadName(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
479 String toscaTemplatePayloadName = uploadResourceInfo.getPayloadName();
480 boolean isValidSuffix = false;
481 if (toscaTemplatePayloadName != null && !toscaTemplatePayloadName.isEmpty()) {
482 for (String validSuffix : TOSCA_YML_CSAR_VALID_SUFFIX) {
483 isValidSuffix = isValidSuffix || toscaTemplatePayloadName.toLowerCase().endsWith(validSuffix);
486 if (!isValidSuffix) {
487 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_FILE_EXTENSION);
488 Response errorResponse = buildErrorResponse(responseFormat);
489 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
490 responseWrapper.setInnerElement(errorResponse);
495 private void validateMD5(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfo, HttpServletRequest request, String resourceInfoJsonString) {
497 String recievedMD5 = request.getHeader(Constants.MD5_HEADER);
498 if (recievedMD5 == null) {
501 String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(resourceInfoJsonString);
502 isValid = calculateMD5.equals(recievedMD5);
505 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_CHECKSUM);
506 Response errorResponse = buildErrorResponse(responseFormat);
507 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
508 responseWrapper.setInnerElement(errorResponse);
512 ComponentTypeEnum validateComponentType(String componentType) {
513 if (componentType == null) {
514 throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR);
516 if (ComponentTypeEnum.RESOURCE_PARAM_NAME.equalsIgnoreCase(componentType)) {
517 return ComponentTypeEnum.RESOURCE;
519 if (ComponentTypeEnum.SERVICE_PARAM_NAME.equalsIgnoreCase(componentType)) {
520 return ComponentTypeEnum.SERVICE;
522 log.debug("Invalid componentType:{}", componentType);
523 throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR, componentType);
527 ComponentTypeEnum convertToComponentType(String componentType) {
528 return validateComponentType(componentType);
531 private void fillToscaTemplateFromJson(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo resourceInfo) {
532 if (resourceInfo.getPayloadData() == null || resourceInfo.getPayloadData().isEmpty()) {
533 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_PAYLOAD);
534 Response errorResponse = buildErrorResponse(responseFormat);
535 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
536 responseWrapper.setInnerElement(errorResponse);
538 String toscaPayload = resourceInfo.getPayloadData();
539 String decodedPayload = new String(Base64.decodeBase64(toscaPayload));
540 yamlStringWrapper.setInnerElement(decodedPayload);
545 void fillPayload(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, String resourceInfoJsonString, ResourceAuthorityTypeEnum resourceAuthorityEnum,
546 File file) throws ZipException {
548 if (responseWrapper.isEmpty()) {
549 if (resourceAuthorityEnum.isBackEndImport()) {
550 // PrePayload Validations
551 if (responseWrapper.isEmpty()) {
552 validateDataNotNull(responseWrapper, file, resourceInfoJsonString);
554 if(!resourceAuthorityEnum.equals(ResourceAuthorityTypeEnum.CSAR_TYPE_BE)){
555 if (responseWrapper.isEmpty()) {
556 validateZip(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
559 // Fill PayLoad From File
560 if (responseWrapper.isEmpty()) {
561 fillToscaTemplateFromZip(yamlStringWrapper, uploadResourceInfoWrapper.getInnerElement().getPayloadName(), file);
565 if (responseWrapper.isEmpty()) {
566 validateCsar(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
569 // Fill PayLoad From File
570 if (responseWrapper.isEmpty()) {
571 fillPayloadDataFromFile(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), file);
577 // Fill PayLoad From JSON
578 if (responseWrapper.isEmpty()) {
579 fillToscaTemplateFromJson(responseWrapper, yamlStringWrapper, user, uploadResourceInfoWrapper.getInnerElement());
587 protected void specificResourceAuthorityValidations(final Wrapper<Response> responseWrapper,
588 final Wrapper<UploadResourceInfo> uploadResourceInfoWrapper,
589 final Wrapper<String> yamlStringWrapper, final User user,
590 final HttpServletRequest request, final String resourceInfoJsonString,
591 final ResourceAuthorityTypeEnum resourceAuthorityEnum) {
593 if (responseWrapper.isEmpty()) {
594 // UI Only Validation
595 if (!resourceAuthorityEnum.isBackEndImport()) {
596 importUIValidations(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, request, resourceInfoJsonString);
599 // User Defined Type Resources
600 if (resourceAuthorityEnum.isUserTypeResource() && !CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {
601 if (responseWrapper.isEmpty()) {
602 validatePayloadNameSpace(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, yamlStringWrapper.getInnerElement());
609 void commonGeneralValidations(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, ResourceAuthorityTypeEnum resourceAuthorityEnum, String userId,
610 String resourceInfoJsonString) {
612 if (responseWrapper.isEmpty()) {
613 validateUserExist(responseWrapper, userWrapper, userId);
616 if (responseWrapper.isEmpty()) {
617 validateUserRole(responseWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum);
620 if (responseWrapper.isEmpty()) {
621 validateAndFillResourceJson(responseWrapper, uploadResourceInfoWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum, resourceInfoJsonString);
624 if (responseWrapper.isEmpty()) {
625 validateToscaTemplatePayloadName(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
627 if (responseWrapper.isEmpty()) {
628 validateResourceType(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
633 private void validateResourceType(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
634 String resourceType = uploadResourceInfo.getResourceType();
635 if (resourceType == null || !ResourceTypeEnum.containsName(resourceType)) {
636 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
637 Response errorResponse = buildErrorResponse(responseFormat);
638 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
639 responseWrapper.setInnerElement(errorResponse);
643 private void importUIValidations(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, HttpServletRequest request, String resourceInfoJsonString) {
644 if (responseWrapper.isEmpty()) {
645 validateMD5(responseWrapper, user, resourceInfo, request, resourceInfoJsonString);
647 if (responseWrapper.isEmpty() && request != null && request.getMethod() != null && request.getMethod().equals("POST")) {
648 validateResourceDoesNotExist(responseWrapper, user, resourceInfo.getName());
652 void commonPayloadValidations(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo uploadResourceInfo) {
654 if (responseWrapper.isEmpty()) {
655 validatePayloadIsYml(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
657 if (responseWrapper.isEmpty()) {
658 validatePayloadIsTosca(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
660 if (responseWrapper.isEmpty()) {
661 validatePayloadIsNotService(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
663 if (responseWrapper.isEmpty()) {
664 validatePayloadIsSingleResource(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
669 void handleImport(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfoObject, String yamlAsString, ResourceAuthorityTypeEnum authority, boolean createNewVersion, String resourceUniqueId) {
670 ImmutablePair<Resource, ActionStatus> createOrUpdateResponse = null;
671 Response response = null;
672 Object representation = null;
673 ImmutablePair<Resource, ActionStatus> importedResourceStatus = null;
674 if (CsarValidationUtils.isCsarPayloadName(resourceInfoObject.getPayloadName())) {
675 log.debug("import resource from csar");
676 importedResourceStatus = importResourceFromUICsar(resourceInfoObject, user, resourceUniqueId);
677 } else if (!authority.isUserTypeResource()) {
678 log.debug("import normative type resource");
679 createOrUpdateResponse = resourceImportManager.importNormativeResource(yamlAsString, resourceInfoObject, user, createNewVersion, true);
681 log.debug("import user resource (not normative type)");
682 createOrUpdateResponse = resourceImportManager.importUserDefinedResource(yamlAsString, resourceInfoObject, user, false);
684 if (createOrUpdateResponse!= null){
685 importedResourceStatus = createOrUpdateResponse;
687 if(importedResourceStatus != null){
689 representation = RepresentationUtils.toRepresentation(importedResourceStatus.left);
690 } catch (IOException e) {
691 log.debug("Error while building resource representation : {}", e.getMessage(), e);
693 response = buildOkResponse(getComponentsUtils().getResponseFormat(importedResourceStatus.right), representation);
695 responseWrapper.setInnerElement(response);
698 private ImmutablePair<Resource, ActionStatus> importResourceFromUICsar(UploadResourceInfo resourceInfoObject, User user, String resourceUniqueId) {
700 Resource newResource;
701 ActionStatus actionStatus;
702 Resource resource = new Resource();
703 String payloadName = resourceInfoObject.getPayloadName();
704 fillResourceFromResourceInfoObject(resource, resourceInfoObject);
706 Map<String, byte[]> csarUIPayload = getCsarFromPayload(resourceInfoObject);
707 getAndValidateCsarYaml(csarUIPayload, resource, user, payloadName);
709 if (resourceUniqueId == null || resourceUniqueId.isEmpty()) {
710 newResource = resourceImportManager.getResourceBusinessLogic().createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, csarUIPayload, payloadName);
711 actionStatus = ActionStatus.CREATED;
713 newResource = resourceImportManager.getResourceBusinessLogic().validateAndUpdateResourceFromCsar(resource, user, csarUIPayload, payloadName, resourceUniqueId);
714 actionStatus = ActionStatus.OK;
716 return new ImmutablePair<>(newResource, actionStatus);
719 private Resource throwComponentException(ResponseFormat responseFormat) {
720 throw new ByResponseFormatComponentException(responseFormat);
723 private void getAndValidateCsarYaml(Map<String, byte[]> csarUIPayload, Resource resource, User user, String csarUUID) {
725 Either<ImmutablePair<String, String>, ResponseFormat> getToscaYamlRes = CsarValidationUtils.getToscaYaml(csarUIPayload, csarUUID, getComponentsUtils());
727 if (getToscaYamlRes.isRight()) {
728 ResponseFormat responseFormat = getToscaYamlRes.right().value();
729 log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat);
730 BeEcompErrorManager.getInstance().logBeDaoSystemError("Creating resource from CSAR: fetching CSAR with id " + csarUUID + " failed");
731 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.CREATE_RESOURCE);
732 throwComponentException(responseFormat);
734 String toscaYaml = getToscaYamlRes.left().value().getValue();
736 log.debug("checking tosca template is valid yml");
737 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
738 boolean isValid = yamlConvertor.isValidYaml(toscaYaml.getBytes());
740 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
741 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
742 throwComponentException(responseFormat);
745 log.debug("checking payload is valid tosca");
746 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaYaml);
747 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
749 if (findFirstToscaStringElement.isRight()) {
752 String defenitionVersionFound = findFirstToscaStringElement.left().value();
753 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
756 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
761 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
762 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
763 throwComponentException(responseFormat);
767 private void fillResourceFromResourceInfoObject(Resource resource, UploadResourceInfo resourceInfoObject) {
768 resourceImportManager.populateResourceMetadata(resourceInfoObject, resource);
769 fillArtifacts(resource, resourceInfoObject);
773 private void fillArtifacts(Resource resource, UploadResourceInfo resourceInfoObject) {
774 if (resource != null && resourceInfoObject != null) {
775 List<UploadArtifactInfo> artifactList = resourceInfoObject.getArtifactList();
776 if (artifactList != null) {
777 Map<String, ArtifactDefinition> artifactsHM = new HashMap<>();
778 for (UploadArtifactInfo artifact : artifactList) {
779 ArtifactDefinition artifactDef = new ArtifactDefinition();
780 artifactDef.setArtifactName(artifact.getArtifactName());
781 artifactDef.setArtifactType(artifact.getArtifactType().getType());
782 artifactDef.setDescription(artifact.getArtifactDescription());
783 artifactDef.setPayloadData(artifact.getArtifactData());
784 artifactDef.setArtifactRef(artifact.getArtifactPath());
785 artifactsHM.put(artifactDef.getArtifactName(), artifactDef);
787 resource.setArtifacts(artifactsHM);
792 private Map<String, byte[]> getCsarFromPayload(UploadResourceInfo innerElement) {
793 String csarUUID = innerElement.getPayloadName();
794 String payloadData = innerElement.getPayloadData();
795 if (payloadData == null) {
796 log.info("Failed to decode received csar {}", csarUUID);
797 throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
800 byte[] decodedPayload = Base64.decodeBase64(payloadData.getBytes(StandardCharsets.UTF_8));
801 if (decodedPayload == null) {
802 log.info("Failed to decode received csar {}", csarUUID);
803 throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
806 Map<String, byte[]> csar = null;
808 csar = ZipUtils.readZip(decodedPayload, false);
809 } catch (final ZipException e) {
810 log.info("Failed to unzip received csar {}", csarUUID, e);
812 if (MapUtils.isEmpty(csar)) {
817 void validateInputStream(final HttpServletRequest request, Wrapper<String> dataWrapper, Wrapper<ResponseFormat> errorWrapper) throws IOException {
818 InputStream inputStream = request.getInputStream();
819 byte[] bytes = IOUtils.toByteArray(inputStream);
820 if (bytes == null || bytes.length == 0) {
821 log.info("Empty body was sent.");
822 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
824 dataWrapper.setInnerElement(new String(bytes, StandardCharsets.UTF_8));
829 <T> void validateClassParse(String data, Wrapper<T> parsedClassWrapper, Supplier<Class<T>> classGen, Wrapper<ResponseFormat> errorWrapper) {
831 T parsedClass = gson.fromJson(data, classGen.get());
832 if (parsedClass == null) {
833 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
835 parsedClassWrapper.setInnerElement(parsedClass);
837 } catch (JsonSyntaxException e) {
838 log.debug("Failed to decode received {} {} to object.", classGen.get().getName(), data, e);
839 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
843 void validateComponentInstanceBusinessLogic(HttpServletRequest request, String containerComponentType, Wrapper<ComponentInstanceBusinessLogic> blWrapper, Wrapper<ResponseFormat> errorWrapper) {
844 ServletContext context = request.getSession().getServletContext();
845 ComponentInstanceBusinessLogic componentInstanceLogic = getComponentInstanceBL(context);
846 if (componentInstanceLogic == null) {
847 log.debug("Unsupported component type {}", containerComponentType);
848 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
850 blWrapper.setInnerElement(componentInstanceLogic);
854 <T> Response buildResponseFromElement(Wrapper<ResponseFormat> errorWrapper, Wrapper<T> attributeWrapper) throws IOException {
856 if (errorWrapper.isEmpty()) {
857 ObjectMapper mapper = new ObjectMapper();
858 String result = mapper.writeValueAsString(attributeWrapper.getInnerElement());
859 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
861 response = buildErrorResponse(errorWrapper.getInnerElement());
866 protected void validateXECOMPInstanceIDHeader(String instanceIdHeader, Wrapper<ResponseFormat> responseWrapper) {
867 ResponseFormat responseFormat;
868 if(StringUtils.isEmpty(instanceIdHeader) ){
869 log.debug("Missing X-ECOMP-InstanceID header");
870 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
871 responseWrapper.setInnerElement(responseFormat);
875 protected void validateHttpCspUserIdHeader(String header, Wrapper<ResponseFormat> responseWrapper) {
876 ResponseFormat responseFormat;
877 if( StringUtils.isEmpty(header)){
878 log.debug("MissingUSER_ID");
879 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_USER_ID);
880 responseWrapper.setInnerElement(responseFormat);
884 <T> Either<T, ResponseFormat> parseToObject(String json, Supplier<Class<T>> classSupplier) {
887 T object = RepresentationUtils.fromRepresentation(json, classSupplier.get());
888 return Either.left(object);
889 } catch (Exception e) {
890 log.debug("Failed to parse json to {} object", classSupplier.get().getName(), e);
891 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
892 return Either.right(responseFormat);
896 public <T> Either<List<T>, ResponseFormat> parseListOfObjects(String json, Type type) {
898 List<T> listOfObjects = gson.fromJson(json, type);
899 return Either.left(listOfObjects);
900 } catch (Exception e) {
901 log.debug("Failed to parse json to {} object", type.getClass().getName(), e);
902 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
903 return Either.right(responseFormat);
906 protected void validateNotEmptyBody(String data) {
907 if (StringUtils.isEmpty(data)) {
908 throw new ByActionStatusComponentException(ActionStatus.MISSING_BODY);