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.IOException;
32 import java.io.InputStream;
33 import java.lang.reflect.Type;
34 import java.nio.charset.StandardCharsets;
35 import java.util.Arrays;
36 import java.util.HashMap;
37 import java.util.List;
39 import java.util.Optional;
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.ByActionStatusComponentException;
56 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
57 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
58 import org.openecomp.sdc.be.config.BeEcompErrorManager;
59 import org.openecomp.sdc.be.config.ConfigurationManager;
60 import org.openecomp.sdc.be.dao.api.ActionStatus;
61 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
62 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
63 import org.openecomp.sdc.be.impl.ComponentsUtils;
64 import org.openecomp.sdc.be.impl.ServletUtils;
65 import org.openecomp.sdc.be.model.ArtifactDefinition;
66 import org.openecomp.sdc.be.model.Resource;
67 import org.openecomp.sdc.be.model.UploadResourceInfo;
68 import org.openecomp.sdc.be.model.User;
69 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
70 import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
71 import org.openecomp.sdc.be.user.Role;
72 import org.openecomp.sdc.be.user.UserBusinessLogic;
73 import org.openecomp.sdc.be.utils.TypeUtils;
74 import org.openecomp.sdc.common.api.Constants;
75 import org.openecomp.sdc.common.api.UploadArtifactInfo;
76 import org.openecomp.sdc.common.datastructure.Wrapper;
77 import org.openecomp.sdc.common.log.wrappers.Logger;
78 import org.openecomp.sdc.common.util.GeneralUtility;
79 import org.openecomp.sdc.common.util.YamlToObjectConverter;
80 import org.openecomp.sdc.common.zip.ZipUtils;
81 import org.openecomp.sdc.common.zip.exception.ZipException;
82 import org.openecomp.sdc.exception.ResponseFormat;
83 import org.yaml.snakeyaml.Yaml;
85 public abstract class AbstractValidationsServlet extends BeGenericServlet {
87 private static final Logger log = Logger.getLogger(AbstractValidationsServlet.class);
88 private static final String TOSCA_SIMPLE_YAML_PREFIX = "tosca_simple_yaml_";
89 private static final List<String> TOSCA_DEFINITION_VERSIONS = Arrays.asList(
90 TOSCA_SIMPLE_YAML_PREFIX + "1_0_0",
91 TOSCA_SIMPLE_YAML_PREFIX + "1_1_0",
92 "tosca_simple_profile_for_nfv_1_0_0",
93 TOSCA_SIMPLE_YAML_PREFIX + "1_0",
94 TOSCA_SIMPLE_YAML_PREFIX + "1_1",
95 TOSCA_SIMPLE_YAML_PREFIX + "1_2");
96 private static final List<String> TOSCA_YML_CSAR_VALID_SUFFIX = Arrays.asList(".yml", ".yaml", ".csar");
98 protected ServletUtils servletUtils;
99 protected ResourceImportManager resourceImportManager;
100 protected final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
103 public AbstractValidationsServlet(UserBusinessLogic userBusinessLogic,
104 ComponentInstanceBusinessLogic componentInstanceBL, ComponentsUtils componentsUtils,
105 ServletUtils servletUtils, ResourceImportManager resourceImportManager) {
106 super(userBusinessLogic, componentsUtils);
107 this.servletUtils = servletUtils;
108 this.resourceImportManager = resourceImportManager;
109 this.componentInstanceBusinessLogic = componentInstanceBL;
112 protected void init() {
115 protected void validateResourceDoesNotExist(Wrapper<Response> responseWrapper, User user, String resourceName) {
116 if (resourceImportManager.isResourceExist(resourceName)) {
117 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESOURCE_ALREADY_EXISTS);
118 Response errorResponse = buildErrorResponse(responseFormat);
119 getComponentsUtils().auditResource(responseFormat, user, resourceName, AuditingActionEnum.IMPORT_RESOURCE);
120 responseWrapper.setInnerElement(errorResponse);
124 protected void validateUserExist(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, String userUserId) {
125 log.debug("get user {} from DB", userUserId);
127 if (userUserId == null) {
128 log.info("user userId is null");
129 Response response = returnMissingInformation(new User());
130 responseWrapper.setInnerElement(response);
134 UserBusinessLogic userAdmin = getServletUtils().getUserAdmin();
136 User user = userAdmin.getUser(userUserId);
137 userWrapper.setInnerElement(user);
138 } catch (ComponentException ce) {
139 log.info("user is not listed. userId={}", userUserId);
140 User user = new User();
141 user.setUserId(userUserId);
142 Response response = returnMissingInformation(user);
143 responseWrapper.setInnerElement(response);
148 protected Response returnMissingInformation(User user) {
149 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_INFORMATION);
150 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
151 return buildErrorResponse(responseFormat);
154 protected void validateDataNotNull(Wrapper<Response> responseWrapper, Object... dataParams) {
155 for (Object dataElement : dataParams) {
156 if (dataElement == null) {
157 log.info("Invalid body was received.");
158 Response response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
159 responseWrapper.setInnerElement(response);
166 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user) {
167 log.debug("validate user role");
168 if (!user.getRole().equals(Role.ADMIN.name()) && !user.getRole().equals(Role.DESIGNER.name())) {
169 log.info("user is not in appropriate role to perform action");
170 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
171 log.debug("audit before sending response");
172 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
174 Response response = buildErrorResponse(responseFormat);
175 errorResponseWrapper.setInnerElement(response);
180 protected void validateZip(final Wrapper<Response> responseWrapper, final File zipFile, final String payloadName) {
181 if (StringUtils.isEmpty(payloadName)) {
182 log.info("Invalid JSON was received. Payload name is empty");
183 final Response errorResponse =
184 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
185 responseWrapper.setInnerElement(errorResponse);
188 final Map<String, byte[]> unzippedFolder;
190 unzippedFolder = ZipUtils.readZip(zipFile, false);
191 } catch (final ZipException e) {
192 log.error("Could not read ZIP file '{}' for validation", zipFile.getName(), e);
193 final Response errorResponse =
194 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
195 responseWrapper.setInnerElement(errorResponse);
198 if (!unzippedFolder.containsKey(payloadName)) {
199 log.info("Could no find payload '{}' in ZIP file '{}'", payloadName, zipFile.getName());
200 final Response errorResponse =
201 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
202 responseWrapper.setInnerElement(errorResponse);
208 protected void validateCsar(final Wrapper<Response> responseWrapper, final File csarFile, final String payloadName) {
209 if (StringUtils.isEmpty(payloadName)) {
210 log.info("Invalid JSON was received. Payload name is empty");
211 Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
212 responseWrapper.setInnerElement(errorResponse);
215 final Map<String, byte[]> unzippedFolder;
217 unzippedFolder = ZipUtils.readZip(csarFile, false);
218 } catch (final ZipException e) {
219 log.error("Could not read CSAR file '{}' for validation", csarFile.getName(), e);
220 final Response errorResponse =
221 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
222 responseWrapper.setInnerElement(errorResponse);
225 if (unzippedFolder.isEmpty()) {
226 log.info("The CSAR file is empty");
227 Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
228 responseWrapper.setInnerElement(errorResponse);
233 protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
234 extractZipContents(yamlStringWrapper, file);
237 public static void extractZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
238 final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
239 String ymlName = unzippedFolder.keySet().iterator().next();
240 fillToscaTemplateFromZip(yamlStringWrapper, ymlName, file);
243 private static void fillToscaTemplateFromZip(final Wrapper<String> yamlStringWrapper, final String payloadName,
244 final File file) throws ZipException {
245 final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
246 final byte[] yamlFileInBytes = unzippedFolder.get(payloadName);
247 final String yamlAsString = new String(yamlFileInBytes, StandardCharsets.UTF_8);
248 log.debug("received yaml: {}", yamlAsString);
249 yamlStringWrapper.setInnerElement(yamlAsString);
252 protected void fillPayloadDataFromFile(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfoWrapper, File file) {
253 try(InputStream fileInputStream = new FileInputStream(file)){
255 byte [] data = new byte[(int)file.length()];
256 if( fileInputStream.read(data) == -1){
257 log.info("Invalid json was received.");
258 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
260 Response errorResp = buildErrorResponse(responseFormat);
261 responseWrapper.setInnerElement(errorResp);
263 String payloadData = Base64.encodeBase64String(data);
264 uploadResourceInfoWrapper.setPayloadData(payloadData);
268 } catch (IOException e) {
269 log.info("Invalid json was received or Error while closing input Stream.");
270 log.debug("Invalid json was received or Error while closing input Stream. {}", e.getMessage(), e);
271 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
273 Response errorResp = buildErrorResponse(responseFormat);
274 responseWrapper.setInnerElement(errorResp);
279 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user, ResourceAuthorityTypeEnum resourceAuthority) {
280 log.debug("validate user role");
281 if (resourceAuthority == ResourceAuthorityTypeEnum.NORMATIVE_TYPE_BE) {
282 if (!user.getRole().equals(Role.ADMIN.name())) {
283 log.info("user is not in appropriate role to perform action");
284 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
285 log.debug("audit before sending response");
286 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
288 Response response = buildErrorResponse(responseFormat);
289 errorResponseWrapper.setInnerElement(response);
292 validateUserRole(errorResponseWrapper, user);
297 protected void validateAndFillResourceJson(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, User user, ResourceAuthorityTypeEnum resourceAuthorityEnum, String resourceInfo) {
300 log.debug("The received json is {}", resourceInfo);
301 UploadResourceInfo resourceInfoObject = gson.fromJson(resourceInfo, UploadResourceInfo.class);
302 if (resourceInfoObject == null) {
305 if (!resourceAuthorityEnum.isBackEndImport()) {
306 isValid = resourceInfoObject.getPayloadName() != null && !resourceInfoObject.getPayloadName().isEmpty();
307 //only resource name is checked
311 uploadResourceInfoWrapper.setInnerElement(resourceInfoObject);
314 } catch (JsonSyntaxException e) {
315 log.debug("Invalid json was received. {}", e.getMessage(), e);
320 log.info("Invalid json was received.");
321 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
322 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
323 Response errorResp = buildErrorResponse(responseFormat);
324 responseWrapper.setInnerElement(errorResp);
328 protected void validateAuthorityType(Wrapper<Response> responseWrapper, String authorityType) {
329 log.debug("The received authority type is {}", authorityType);
330 ResourceAuthorityTypeEnum authorityTypeEnum = ResourceAuthorityTypeEnum.findByUrlPath(authorityType);
331 if (authorityTypeEnum == null) {
332 log.info("Invalid authority type was received.");
333 Response errorResp = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
334 responseWrapper.setInnerElement(errorResp);
338 public ServletUtils getServletUtils() {
342 public Gson getGson() {
343 return getServletUtils().getGson();
346 public ComponentsUtils getComponentsUtils() {
347 return getServletUtils().getComponentsUtils();
350 protected void validatePayloadIsTosca(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
351 log.debug("checking payload is valid tosca");
353 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
354 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
356 if (findFirstToscaStringElement.isRight()) {
359 String defenitionVersionFound = findFirstToscaStringElement.left().value();
360 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
363 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
368 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
369 Response errorResponse = buildErrorResponse(responseFormat);
370 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
371 responseWrapper.setInnerElement(errorResponse);
376 protected void validatePayloadIsYml(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaTamplatePayload) {
377 log.debug("checking tosca template is valid yml");
378 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
379 boolean isYamlValid = yamlConvertor.isValidYaml(toscaTamplatePayload.getBytes());
381 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
382 Response errorResponse = buildErrorResponse(responseFormat);
383 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
384 responseWrapper.setInnerElement(errorResponse);
389 * Gets the Resource type from the given node type name.
391 * @param nodeTypeFullName - Node type Name
392 * @return Resource Type name
394 private String getResourceType(final String nodeTypeFullName) {
396 final Optional<String> nodeTypeNamePrefix = getNodeTypeNamePrefix(nodeTypeFullName);
397 if (nodeTypeNamePrefix.isPresent()) {
398 final String nameWithouNamespacePrefix = nodeTypeFullName.substring(nodeTypeNamePrefix.get().length());
399 final String[] findTypes = nameWithouNamespacePrefix.split("\\.");
400 if (findTypes.length > 0) {
401 final ResourceTypeEnum resourceType = ResourceTypeEnum.getType(findTypes[0].toUpperCase());
402 if (resourceType != null) {
403 return resourceType.name();
407 return ResourceTypeEnum.VFC.name();
411 * Extracts the Node Type Name prefix from the given Node Type Name.
412 * @param nodeName - Node Type Name
413 * @return Node Type Name prefix
415 private Optional<String> getNodeTypeNamePrefix(final String nodeName) {
416 final List<String> definedNodeTypeNamespaceList = ConfigurationManager.getConfigurationManager()
417 .getConfiguration().getDefinedResourceNamespace();
418 for (final String validNamespace : definedNodeTypeNamespaceList) {
419 if (nodeName.startsWith(validNamespace)) {
420 return Optional.of(validNamespace);
423 return Optional.empty();
426 protected void validatePayloadNameSpace(final Wrapper<Response> responseWrapper,
427 final UploadResourceInfo resourceInfo,
428 final User user, final String toscaPayload) {
430 String namespace = "";
431 final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
432 final Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
433 if (toscaElement.isRight() || toscaElement.left().value().size() != 1) {
436 namespace = toscaElement.left().value().keySet().iterator().next();
437 isValid = getNodeTypeNamePrefix(namespace).isPresent();
440 final ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_NAMESPACE);
441 final Response errorResponse = buildErrorResponse(responseFormat);
442 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
443 responseWrapper.setInnerElement(errorResponse);
445 resourceInfo.setResourceType(getResourceType(namespace));
449 private void validatePayloadIsSingleResource(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
450 log.debug("checking payload contains single resource");
452 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
453 Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
454 if (toscaElement.isRight()) {
457 isValid = toscaElement.left().value().size() == 1;
461 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_SINGLE_RESOURCE);
462 Response errorResponse = buildErrorResponse(responseFormat);
463 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
464 responseWrapper.setInnerElement(errorResponse);
469 private void validatePayloadIsNotService(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaPayload) {
470 log.debug("checking payload is not a tosca service");
471 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
472 Either<Object, ResultStatusEnum> toscaElement = ImportUtils.findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL);
474 if (toscaElement.isLeft()) {
475 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_RESOURCE_TOSCA_TEMPLATE);
476 Response errorResponse = buildErrorResponse(responseFormat);
477 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
478 responseWrapper.setInnerElement(errorResponse);
483 private void validateToscaTemplatePayloadName(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
484 String toscaTemplatePayloadName = uploadResourceInfo.getPayloadName();
485 boolean isValidSuffix = false;
486 if (toscaTemplatePayloadName != null && !toscaTemplatePayloadName.isEmpty()) {
487 for (String validSuffix : TOSCA_YML_CSAR_VALID_SUFFIX) {
488 isValidSuffix = isValidSuffix || toscaTemplatePayloadName.toLowerCase().endsWith(validSuffix);
491 if (!isValidSuffix) {
492 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_FILE_EXTENSION);
493 Response errorResponse = buildErrorResponse(responseFormat);
494 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
495 responseWrapper.setInnerElement(errorResponse);
500 private void validateMD5(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfo, HttpServletRequest request, String resourceInfoJsonString) {
502 String recievedMD5 = request.getHeader(Constants.MD5_HEADER);
503 if (recievedMD5 == null) {
506 String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(resourceInfoJsonString);
507 isValid = calculateMD5.equals(recievedMD5);
510 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_CHECKSUM);
511 Response errorResponse = buildErrorResponse(responseFormat);
512 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
513 responseWrapper.setInnerElement(errorResponse);
517 ComponentTypeEnum validateComponentType(String componentType) {
518 if (componentType == null) {
519 throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR);
521 if (ComponentTypeEnum.RESOURCE_PARAM_NAME.equalsIgnoreCase(componentType)) {
522 return ComponentTypeEnum.RESOURCE;
524 if (ComponentTypeEnum.SERVICE_PARAM_NAME.equalsIgnoreCase(componentType)) {
525 return ComponentTypeEnum.SERVICE;
527 log.debug("Invalid componentType:{}", componentType);
528 throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR, componentType);
532 ComponentTypeEnum convertToComponentType(String componentType) {
533 return validateComponentType(componentType);
536 private void fillToscaTemplateFromJson(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo resourceInfo) {
537 if (resourceInfo.getPayloadData() == null || resourceInfo.getPayloadData().isEmpty()) {
538 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_PAYLOAD);
539 Response errorResponse = buildErrorResponse(responseFormat);
540 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
541 responseWrapper.setInnerElement(errorResponse);
543 String toscaPayload = resourceInfo.getPayloadData();
544 String decodedPayload = new String(Base64.decodeBase64(toscaPayload));
545 yamlStringWrapper.setInnerElement(decodedPayload);
550 void fillPayload(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, String resourceInfoJsonString, ResourceAuthorityTypeEnum resourceAuthorityEnum,
551 File file) throws ZipException {
553 if (responseWrapper.isEmpty()) {
554 if (resourceAuthorityEnum.isBackEndImport()) {
555 // PrePayload Validations
556 if (responseWrapper.isEmpty()) {
557 validateDataNotNull(responseWrapper, file, resourceInfoJsonString);
559 if(!resourceAuthorityEnum.equals(ResourceAuthorityTypeEnum.CSAR_TYPE_BE)){
560 if (responseWrapper.isEmpty()) {
561 validateZip(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
564 // Fill PayLoad From File
565 if (responseWrapper.isEmpty()) {
566 fillToscaTemplateFromZip(yamlStringWrapper, uploadResourceInfoWrapper.getInnerElement().getPayloadName(), file);
570 if (responseWrapper.isEmpty()) {
571 validateCsar(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
574 // Fill PayLoad From File
575 if (responseWrapper.isEmpty()) {
576 fillPayloadDataFromFile(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), file);
582 // Fill PayLoad From JSON
583 if (responseWrapper.isEmpty()) {
584 fillToscaTemplateFromJson(responseWrapper, yamlStringWrapper, user, uploadResourceInfoWrapper.getInnerElement());
592 protected void specificResourceAuthorityValidations(final Wrapper<Response> responseWrapper,
593 final Wrapper<UploadResourceInfo> uploadResourceInfoWrapper,
594 final Wrapper<String> yamlStringWrapper, final User user,
595 final HttpServletRequest request, final String resourceInfoJsonString,
596 final ResourceAuthorityTypeEnum resourceAuthorityEnum) {
598 if (responseWrapper.isEmpty()) {
599 // UI Only Validation
600 if (!resourceAuthorityEnum.isBackEndImport()) {
601 importUIValidations(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, request, resourceInfoJsonString);
604 // User Defined Type Resources
605 if (resourceAuthorityEnum.isUserTypeResource()
606 && !CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())
607 && responseWrapper.isEmpty()) {
608 validatePayloadNameSpace(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, yamlStringWrapper.getInnerElement());
613 void commonGeneralValidations(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, ResourceAuthorityTypeEnum resourceAuthorityEnum, String userId,
614 String resourceInfoJsonString) {
616 if (responseWrapper.isEmpty()) {
617 validateUserExist(responseWrapper, userWrapper, userId);
620 if (responseWrapper.isEmpty()) {
621 validateUserRole(responseWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum);
624 if (responseWrapper.isEmpty()) {
625 validateAndFillResourceJson(responseWrapper, uploadResourceInfoWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum, resourceInfoJsonString);
628 if (responseWrapper.isEmpty()) {
629 validateToscaTemplatePayloadName(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
631 if (responseWrapper.isEmpty()) {
632 validateResourceType(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
637 private void validateResourceType(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
638 String resourceType = uploadResourceInfo.getResourceType();
639 if (resourceType == null || !ResourceTypeEnum.containsName(resourceType)) {
640 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
641 Response errorResponse = buildErrorResponse(responseFormat);
642 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
643 responseWrapper.setInnerElement(errorResponse);
647 private void importUIValidations(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, HttpServletRequest request, String resourceInfoJsonString) {
648 if (responseWrapper.isEmpty()) {
649 validateMD5(responseWrapper, user, resourceInfo, request, resourceInfoJsonString);
651 if (responseWrapper.isEmpty() && request != null && request.getMethod() != null && request.getMethod().equals("POST")) {
652 validateResourceDoesNotExist(responseWrapper, user, resourceInfo.getName());
656 void commonPayloadValidations(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo uploadResourceInfo) {
658 if (responseWrapper.isEmpty()) {
659 validatePayloadIsYml(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
661 if (responseWrapper.isEmpty()) {
662 validatePayloadIsTosca(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
664 if (responseWrapper.isEmpty()) {
665 validatePayloadIsNotService(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
667 if (responseWrapper.isEmpty()) {
668 validatePayloadIsSingleResource(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
673 void handleImport(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfoObject, String yamlAsString, ResourceAuthorityTypeEnum authority, boolean createNewVersion, String resourceUniqueId) {
674 ImmutablePair<Resource, ActionStatus> createOrUpdateResponse = null;
675 Response response = null;
676 Object representation = null;
677 ImmutablePair<Resource, ActionStatus> importedResourceStatus = null;
678 if (CsarValidationUtils.isCsarPayloadName(resourceInfoObject.getPayloadName())) {
679 log.debug("import resource from csar");
680 importedResourceStatus = importResourceFromUICsar(resourceInfoObject, user, resourceUniqueId);
681 } else if (!authority.isUserTypeResource()) {
682 log.debug("import normative type resource");
683 createOrUpdateResponse = resourceImportManager.importNormativeResource(yamlAsString, resourceInfoObject, user, createNewVersion, true);
685 log.debug("import user resource (not normative type)");
686 createOrUpdateResponse = resourceImportManager.importUserDefinedResource(yamlAsString, resourceInfoObject, user, false);
688 if (createOrUpdateResponse!= null){
689 importedResourceStatus = createOrUpdateResponse;
691 if(importedResourceStatus != null){
693 representation = RepresentationUtils.toRepresentation(importedResourceStatus.left);
694 } catch (IOException e) {
695 log.debug("Error while building resource representation : {}", e.getMessage(), e);
697 response = buildOkResponse(getComponentsUtils().getResponseFormat(importedResourceStatus.right), representation);
699 responseWrapper.setInnerElement(response);
702 private ImmutablePair<Resource, ActionStatus> importResourceFromUICsar(UploadResourceInfo resourceInfoObject, User user, String resourceUniqueId) {
704 Resource newResource;
705 ActionStatus actionStatus;
706 Resource resource = new Resource();
707 String payloadName = resourceInfoObject.getPayloadName();
708 fillResourceFromResourceInfoObject(resource, resourceInfoObject);
710 Map<String, byte[]> csarUIPayload = getCsarFromPayload(resourceInfoObject);
711 getAndValidateCsarYaml(csarUIPayload, resource, user, payloadName);
713 if (resourceUniqueId == null || resourceUniqueId.isEmpty()) {
714 newResource = resourceImportManager.getResourceBusinessLogic().createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, csarUIPayload, payloadName);
715 actionStatus = ActionStatus.CREATED;
717 newResource = resourceImportManager.getResourceBusinessLogic().validateAndUpdateResourceFromCsar(resource, user, csarUIPayload, payloadName, resourceUniqueId);
718 actionStatus = ActionStatus.OK;
720 return new ImmutablePair<>(newResource, actionStatus);
723 private Resource throwComponentException(ResponseFormat responseFormat) {
724 throw new ByResponseFormatComponentException(responseFormat);
727 private void getAndValidateCsarYaml(Map<String, byte[]> csarUIPayload, Resource resource, User user, String csarUUID) {
729 Either<ImmutablePair<String, String>, ResponseFormat> getToscaYamlRes = CsarValidationUtils.getToscaYaml(csarUIPayload, csarUUID, getComponentsUtils());
731 if (getToscaYamlRes.isRight()) {
732 ResponseFormat responseFormat = getToscaYamlRes.right().value();
733 log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat);
734 BeEcompErrorManager.getInstance().logBeDaoSystemError("Creating resource from CSAR: fetching CSAR with id " + csarUUID + " failed");
735 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.CREATE_RESOURCE);
736 throwComponentException(responseFormat);
738 String toscaYaml = getToscaYamlRes.left().value().getValue();
740 log.debug("checking tosca template is valid yml");
741 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
742 boolean isValid = yamlConvertor.isValidYaml(toscaYaml.getBytes());
744 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
745 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
746 throwComponentException(responseFormat);
749 log.debug("checking payload is valid tosca");
750 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaYaml);
751 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
753 if (findFirstToscaStringElement.isRight()) {
756 String defenitionVersionFound = findFirstToscaStringElement.left().value();
757 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
760 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
765 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
766 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
767 throwComponentException(responseFormat);
771 private void fillResourceFromResourceInfoObject(Resource resource, UploadResourceInfo resourceInfoObject) {
772 resourceImportManager.populateResourceMetadata(resourceInfoObject, resource);
773 fillArtifacts(resource, resourceInfoObject);
777 private void fillArtifacts(Resource resource, UploadResourceInfo resourceInfoObject) {
778 if (resource != null && resourceInfoObject != null) {
779 List<UploadArtifactInfo> artifactList = resourceInfoObject.getArtifactList();
780 if (artifactList != null) {
781 Map<String, ArtifactDefinition> artifactsHM = new HashMap<>();
782 for (UploadArtifactInfo artifact : artifactList) {
783 ArtifactDefinition artifactDef = new ArtifactDefinition();
784 artifactDef.setArtifactName(artifact.getArtifactName());
785 artifactDef.setArtifactType(artifact.getArtifactType().getType());
786 artifactDef.setDescription(artifact.getArtifactDescription());
787 artifactDef.setPayloadData(artifact.getArtifactData());
788 artifactDef.setArtifactRef(artifact.getArtifactPath());
789 artifactsHM.put(artifactDef.getArtifactName(), artifactDef);
791 resource.setArtifacts(artifactsHM);
796 private Map<String, byte[]> getCsarFromPayload(UploadResourceInfo innerElement) {
797 String csarUUID = innerElement.getPayloadName();
798 String payloadData = innerElement.getPayloadData();
799 if (payloadData == null) {
800 log.info("Failed to decode received csar {}", csarUUID);
801 throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
804 byte[] decodedPayload = Base64.decodeBase64(payloadData.getBytes(StandardCharsets.UTF_8));
805 if (decodedPayload == null) {
806 log.info("Failed to decode received csar {}", csarUUID);
807 throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
810 Map<String, byte[]> csar = null;
812 csar = ZipUtils.readZip(decodedPayload, false);
813 } catch (final ZipException e) {
814 log.info("Failed to unzip received csar {}", csarUUID, e);
819 void validateInputStream(final HttpServletRequest request, Wrapper<String> dataWrapper, Wrapper<ResponseFormat> errorWrapper) throws IOException {
820 InputStream inputStream = request.getInputStream();
821 byte[] bytes = IOUtils.toByteArray(inputStream);
822 if (bytes == null || bytes.length == 0) {
823 log.info("Empty body was sent.");
824 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
826 dataWrapper.setInnerElement(new String(bytes, StandardCharsets.UTF_8));
831 <T> void validateClassParse(String data, Wrapper<T> parsedClassWrapper, Supplier<Class<T>> classGen, Wrapper<ResponseFormat> errorWrapper) {
833 T parsedClass = gson.fromJson(data, classGen.get());
834 if (parsedClass == null) {
835 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
837 parsedClassWrapper.setInnerElement(parsedClass);
839 } catch (JsonSyntaxException e) {
840 log.debug("Failed to decode received {} {} to object.", classGen.get().getName(), data, e);
841 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
845 void validateComponentInstanceBusinessLogic(HttpServletRequest request, String containerComponentType, Wrapper<ComponentInstanceBusinessLogic> blWrapper, Wrapper<ResponseFormat> errorWrapper) {
846 ServletContext context = request.getSession().getServletContext();
847 ComponentInstanceBusinessLogic componentInstanceLogic = getComponentInstanceBL(context);
848 if (componentInstanceLogic == null) {
849 log.debug("Unsupported component type {}", containerComponentType);
850 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
852 blWrapper.setInnerElement(componentInstanceLogic);
856 <T> Response buildResponseFromElement(Wrapper<ResponseFormat> errorWrapper, Wrapper<T> attributeWrapper) throws IOException {
858 if (errorWrapper.isEmpty()) {
859 ObjectMapper mapper = new ObjectMapper();
860 String result = mapper.writeValueAsString(attributeWrapper.getInnerElement());
861 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
863 response = buildErrorResponse(errorWrapper.getInnerElement());
868 protected void validateXECOMPInstanceIDHeader(String instanceIdHeader, Wrapper<ResponseFormat> responseWrapper) {
869 ResponseFormat responseFormat;
870 if(StringUtils.isEmpty(instanceIdHeader) ){
871 log.debug("Missing X-ECOMP-InstanceID header");
872 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
873 responseWrapper.setInnerElement(responseFormat);
877 protected void validateHttpCspUserIdHeader(String header, Wrapper<ResponseFormat> responseWrapper) {
878 ResponseFormat responseFormat;
879 if( StringUtils.isEmpty(header)){
880 log.debug("MissingUSER_ID");
881 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_USER_ID);
882 responseWrapper.setInnerElement(responseFormat);
886 <T> Either<T, ResponseFormat> parseToObject(String json, Supplier<Class<T>> classSupplier) {
889 T object = RepresentationUtils.fromRepresentation(json, classSupplier.get());
890 return Either.left(object);
891 } catch (Exception e) {
892 log.debug("Failed to parse json to {} object", classSupplier.get().getName(), e);
893 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
894 return Either.right(responseFormat);
898 public <T> Either<List<T>, ResponseFormat> parseListOfObjects(String json, Type type) {
900 List<T> listOfObjects = gson.fromJson(json, type);
901 return Either.left(listOfObjects);
902 } catch (Exception e) {
903 log.debug("Failed to parse json to {} object", type.getClass().getName(), e);
904 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
905 return Either.right(responseFormat);
908 protected void validateNotEmptyBody(String data) {
909 if (StringUtils.isEmpty(data)) {
910 throw new ByActionStatusComponentException(ActionStatus.MISSING_BODY);