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(
91 TOSCA_SIMPLE_YAML_PREFIX + "1_0_0",
92 TOSCA_SIMPLE_YAML_PREFIX + "1_1_0",
93 "tosca_simple_profile_for_nfv_1_0_0",
94 TOSCA_SIMPLE_YAML_PREFIX + "1_0",
95 TOSCA_SIMPLE_YAML_PREFIX + "1_1",
96 TOSCA_SIMPLE_YAML_PREFIX + "1_2");
97 private static final List<String> TOSCA_YML_CSAR_VALID_SUFFIX = Arrays.asList(".yml", ".yaml", ".csar");
99 protected ServletUtils servletUtils;
100 protected ResourceImportManager resourceImportManager;
101 protected final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
104 public AbstractValidationsServlet(UserBusinessLogic userBusinessLogic,
105 ComponentInstanceBusinessLogic componentInstanceBL, ComponentsUtils componentsUtils,
106 ServletUtils servletUtils, ResourceImportManager resourceImportManager) {
107 super(userBusinessLogic, componentsUtils);
108 this.servletUtils = servletUtils;
109 this.resourceImportManager = resourceImportManager;
110 this.componentInstanceBusinessLogic = componentInstanceBL;
113 protected void init() {
116 protected void validateResourceDoesNotExist(Wrapper<Response> responseWrapper, User user, String resourceName) {
117 if (resourceImportManager.isResourceExist(resourceName)) {
118 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESOURCE_ALREADY_EXISTS);
119 Response errorResponse = buildErrorResponse(responseFormat);
120 getComponentsUtils().auditResource(responseFormat, user, resourceName, AuditingActionEnum.IMPORT_RESOURCE);
121 responseWrapper.setInnerElement(errorResponse);
125 protected void validateUserExist(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, String userUserId) {
126 log.debug("get user {} from DB", userUserId);
128 if (userUserId == null) {
129 log.info("user userId is null");
130 Response response = returnMissingInformation(new User());
131 responseWrapper.setInnerElement(response);
135 UserBusinessLogic userAdmin = getServletUtils().getUserAdmin();
137 User user = userAdmin.getUser(userUserId);
138 userWrapper.setInnerElement(user);
139 } catch (ComponentException ce) {
140 log.info("user is not listed. userId={}", userUserId);
141 User user = new User();
142 user.setUserId(userUserId);
143 Response response = returnMissingInformation(user);
144 responseWrapper.setInnerElement(response);
149 protected Response returnMissingInformation(User user) {
150 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_INFORMATION);
151 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
152 return buildErrorResponse(responseFormat);
155 protected void validateDataNotNull(Wrapper<Response> responseWrapper, Object... dataParams) {
156 for (Object dataElement : dataParams) {
157 if (dataElement == null) {
158 log.info("Invalid body was received.");
159 Response response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
160 responseWrapper.setInnerElement(response);
167 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user) {
168 log.debug("validate user role");
169 if (!user.getRole().equals(Role.ADMIN.name()) && !user.getRole().equals(Role.DESIGNER.name())) {
170 log.info("user is not in appropriate role to perform action");
171 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
172 log.debug("audit before sending response");
173 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
175 Response response = buildErrorResponse(responseFormat);
176 errorResponseWrapper.setInnerElement(response);
181 protected void validateZip(final Wrapper<Response> responseWrapper, final File zipFile, final String payloadName) {
182 if (StringUtils.isEmpty(payloadName)) {
183 log.info("Invalid JSON was received. Payload name is empty");
184 final Response errorResponse =
185 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
186 responseWrapper.setInnerElement(errorResponse);
189 final Map<String, byte[]> unzippedFolder;
191 unzippedFolder = ZipUtils.readZip(zipFile, false);
192 } catch (final ZipException e) {
193 log.error("Could not read ZIP file '{}' for validation", zipFile.getName(), e);
194 final Response errorResponse =
195 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
196 responseWrapper.setInnerElement(errorResponse);
199 if (!unzippedFolder.containsKey(payloadName)) {
200 log.info("Could no find payload '{}' in ZIP file '{}'", payloadName, zipFile.getName());
201 final Response errorResponse =
202 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
203 responseWrapper.setInnerElement(errorResponse);
209 protected void validateCsar(final Wrapper<Response> responseWrapper, final File csarFile, final String payloadName) {
210 if (StringUtils.isEmpty(payloadName)) {
211 log.info("Invalid JSON was received. Payload name is empty");
212 Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
213 responseWrapper.setInnerElement(errorResponse);
216 final Map<String, byte[]> unzippedFolder;
218 unzippedFolder = ZipUtils.readZip(csarFile, false);
219 } catch (final ZipException e) {
220 log.error("Could not read CSAR file '{}' for validation", csarFile.getName(), e);
221 final Response errorResponse =
222 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
223 responseWrapper.setInnerElement(errorResponse);
226 if (unzippedFolder.isEmpty()) {
227 log.info("The CSAR file is empty");
228 Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
229 responseWrapper.setInnerElement(errorResponse);
234 protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
235 extractZipContents(yamlStringWrapper, file);
238 public static void extractZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
239 final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
240 String ymlName = unzippedFolder.keySet().iterator().next();
241 fillToscaTemplateFromZip(yamlStringWrapper, ymlName, file);
244 private static void fillToscaTemplateFromZip(final Wrapper<String> yamlStringWrapper, final String payloadName,
245 final File file) throws ZipException {
246 final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
247 final byte[] yamlFileInBytes = unzippedFolder.get(payloadName);
248 final String yamlAsString = new String(yamlFileInBytes, StandardCharsets.UTF_8);
249 log.debug("received yaml: {}", yamlAsString);
250 yamlStringWrapper.setInnerElement(yamlAsString);
253 protected void fillPayloadDataFromFile(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfoWrapper, File file) {
254 try(InputStream fileInputStream = new FileInputStream(file)){
256 byte [] data = new byte[(int)file.length()];
257 if( fileInputStream.read(data) == -1){
258 log.info("Invalid json was received.");
259 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
261 Response errorResp = buildErrorResponse(responseFormat);
262 responseWrapper.setInnerElement(errorResp);
264 String payloadData = Base64.encodeBase64String(data);
265 uploadResourceInfoWrapper.setPayloadData(payloadData);
269 } catch (IOException e) {
270 log.info("Invalid json was received or Error while closing input Stream.");
271 log.debug("Invalid json was received or Error while closing input Stream. {}", e.getMessage(), e);
272 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
274 Response errorResp = buildErrorResponse(responseFormat);
275 responseWrapper.setInnerElement(errorResp);
280 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user, ResourceAuthorityTypeEnum resourceAuthority) {
281 log.debug("validate user role");
282 if (resourceAuthority == ResourceAuthorityTypeEnum.NORMATIVE_TYPE_BE) {
283 if (!user.getRole().equals(Role.ADMIN.name())) {
284 log.info("user is not in appropriate role to perform action");
285 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
286 log.debug("audit before sending response");
287 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
289 Response response = buildErrorResponse(responseFormat);
290 errorResponseWrapper.setInnerElement(response);
293 validateUserRole(errorResponseWrapper, user);
298 protected void validateAndFillResourceJson(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, User user, ResourceAuthorityTypeEnum resourceAuthorityEnum, String resourceInfo) {
301 log.debug("The received json is {}", resourceInfo);
302 UploadResourceInfo resourceInfoObject = gson.fromJson(resourceInfo, UploadResourceInfo.class);
303 if (resourceInfoObject == null) {
306 if (!resourceAuthorityEnum.isBackEndImport()) {
307 isValid = resourceInfoObject.getPayloadName() != null && !resourceInfoObject.getPayloadName().isEmpty();
308 //only resource name is checked
312 uploadResourceInfoWrapper.setInnerElement(resourceInfoObject);
315 } catch (JsonSyntaxException e) {
316 log.debug("Invalid json was received. {}", e.getMessage(), e);
321 log.info("Invalid json was received.");
322 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
323 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
324 Response errorResp = buildErrorResponse(responseFormat);
325 responseWrapper.setInnerElement(errorResp);
329 protected void validateAuthorityType(Wrapper<Response> responseWrapper, String authorityType) {
330 log.debug("The received authority type is {}", authorityType);
331 ResourceAuthorityTypeEnum authorityTypeEnum = ResourceAuthorityTypeEnum.findByUrlPath(authorityType);
332 if (authorityTypeEnum == null) {
333 log.info("Invalid authority type was received.");
334 Response errorResp = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
335 responseWrapper.setInnerElement(errorResp);
339 public ServletUtils getServletUtils() {
343 public Gson getGson() {
344 return getServletUtils().getGson();
347 public ComponentsUtils getComponentsUtils() {
348 return getServletUtils().getComponentsUtils();
351 protected void validatePayloadIsTosca(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
352 log.debug("checking payload is valid tosca");
354 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
355 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
357 if (findFirstToscaStringElement.isRight()) {
360 String defenitionVersionFound = findFirstToscaStringElement.left().value();
361 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
364 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
369 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
370 Response errorResponse = buildErrorResponse(responseFormat);
371 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
372 responseWrapper.setInnerElement(errorResponse);
377 protected void validatePayloadIsYml(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaTamplatePayload) {
378 log.debug("checking tosca template is valid yml");
379 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
380 boolean isYamlValid = yamlConvertor.isValidYaml(toscaTamplatePayload.getBytes());
382 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
383 Response errorResponse = buildErrorResponse(responseFormat);
384 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
385 responseWrapper.setInnerElement(errorResponse);
390 * Gets the Resource type from the given node type name.
392 * @param nodeTypeFullName - Node type Name
393 * @return Resource Type name
395 private String getResourceType(final String nodeTypeFullName) {
397 final Optional<String> nodeTypeNamePrefix = getNodeTypeNamePrefix(nodeTypeFullName);
398 if (nodeTypeNamePrefix.isPresent()) {
399 final String nameWithouNamespacePrefix = nodeTypeFullName.substring(nodeTypeNamePrefix.get().length());
400 final String[] findTypes = nameWithouNamespacePrefix.split("\\.");
401 if (findTypes.length > 0) {
402 final ResourceTypeEnum resourceType = ResourceTypeEnum.getType(findTypes[0].toUpperCase());
403 if (resourceType != null) {
404 return resourceType.name();
408 return ResourceTypeEnum.VFC.name();
412 * Extracts the Node Type Name prefix from the given Node Type Name.
413 * @param nodeName - Node Type Name
414 * @return Node Type Name prefix
416 private Optional<String> getNodeTypeNamePrefix(final String nodeName) {
417 final List<String> definedNodeTypeNamespaceList = ConfigurationManager.getConfigurationManager()
418 .getConfiguration().getDefinedResourceNamespace();
419 for (final String validNamespace : definedNodeTypeNamespaceList) {
420 if (nodeName.startsWith(validNamespace)) {
421 return Optional.of(validNamespace);
424 return Optional.empty();
427 protected void validatePayloadNameSpace(final Wrapper<Response> responseWrapper,
428 final UploadResourceInfo resourceInfo,
429 final User user, final String toscaPayload) {
431 String namespace = "";
432 final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
433 final Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
434 if (toscaElement.isRight() || toscaElement.left().value().size() != 1) {
437 namespace = toscaElement.left().value().keySet().iterator().next();
438 isValid = getNodeTypeNamePrefix(namespace).isPresent();
441 final ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_NAMESPACE);
442 final Response errorResponse = buildErrorResponse(responseFormat);
443 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
444 responseWrapper.setInnerElement(errorResponse);
446 resourceInfo.setResourceType(getResourceType(namespace));
450 private void validatePayloadIsSingleResource(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
451 log.debug("checking payload contains single resource");
453 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
454 Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
455 if (toscaElement.isRight()) {
458 isValid = toscaElement.left().value().size() == 1;
462 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_SINGLE_RESOURCE);
463 Response errorResponse = buildErrorResponse(responseFormat);
464 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
465 responseWrapper.setInnerElement(errorResponse);
470 private void validatePayloadIsNotService(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaPayload) {
471 log.debug("checking payload is not a tosca service");
472 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
473 Either<Object, ResultStatusEnum> toscaElement = ImportUtils.findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL);
475 if (toscaElement.isLeft()) {
476 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_RESOURCE_TOSCA_TEMPLATE);
477 Response errorResponse = buildErrorResponse(responseFormat);
478 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
479 responseWrapper.setInnerElement(errorResponse);
484 private void validateToscaTemplatePayloadName(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
485 String toscaTemplatePayloadName = uploadResourceInfo.getPayloadName();
486 boolean isValidSuffix = false;
487 if (toscaTemplatePayloadName != null && !toscaTemplatePayloadName.isEmpty()) {
488 for (String validSuffix : TOSCA_YML_CSAR_VALID_SUFFIX) {
489 isValidSuffix = isValidSuffix || toscaTemplatePayloadName.toLowerCase().endsWith(validSuffix);
492 if (!isValidSuffix) {
493 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_FILE_EXTENSION);
494 Response errorResponse = buildErrorResponse(responseFormat);
495 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
496 responseWrapper.setInnerElement(errorResponse);
501 private void validateMD5(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfo, HttpServletRequest request, String resourceInfoJsonString) {
503 String recievedMD5 = request.getHeader(Constants.MD5_HEADER);
504 if (recievedMD5 == null) {
507 String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(resourceInfoJsonString);
508 isValid = calculateMD5.equals(recievedMD5);
511 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_CHECKSUM);
512 Response errorResponse = buildErrorResponse(responseFormat);
513 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
514 responseWrapper.setInnerElement(errorResponse);
518 ComponentTypeEnum validateComponentType(String componentType) {
519 if (componentType == null) {
520 throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR);
522 if (ComponentTypeEnum.RESOURCE_PARAM_NAME.equalsIgnoreCase(componentType)) {
523 return ComponentTypeEnum.RESOURCE;
525 if (ComponentTypeEnum.SERVICE_PARAM_NAME.equalsIgnoreCase(componentType)) {
526 return ComponentTypeEnum.SERVICE;
528 log.debug("Invalid componentType:{}", componentType);
529 throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR, componentType);
533 ComponentTypeEnum convertToComponentType(String componentType) {
534 return validateComponentType(componentType);
537 private void fillToscaTemplateFromJson(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo resourceInfo) {
538 if (resourceInfo.getPayloadData() == null || resourceInfo.getPayloadData().isEmpty()) {
539 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_PAYLOAD);
540 Response errorResponse = buildErrorResponse(responseFormat);
541 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
542 responseWrapper.setInnerElement(errorResponse);
544 String toscaPayload = resourceInfo.getPayloadData();
545 String decodedPayload = new String(Base64.decodeBase64(toscaPayload));
546 yamlStringWrapper.setInnerElement(decodedPayload);
551 void fillPayload(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, String resourceInfoJsonString, ResourceAuthorityTypeEnum resourceAuthorityEnum,
552 File file) throws ZipException {
554 if (responseWrapper.isEmpty()) {
555 if (resourceAuthorityEnum.isBackEndImport()) {
556 // PrePayload Validations
557 if (responseWrapper.isEmpty()) {
558 validateDataNotNull(responseWrapper, file, resourceInfoJsonString);
560 if(!resourceAuthorityEnum.equals(ResourceAuthorityTypeEnum.CSAR_TYPE_BE)){
561 if (responseWrapper.isEmpty()) {
562 validateZip(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
565 // Fill PayLoad From File
566 if (responseWrapper.isEmpty()) {
567 fillToscaTemplateFromZip(yamlStringWrapper, uploadResourceInfoWrapper.getInnerElement().getPayloadName(), file);
571 if (responseWrapper.isEmpty()) {
572 validateCsar(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
575 // Fill PayLoad From File
576 if (responseWrapper.isEmpty()) {
577 fillPayloadDataFromFile(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), file);
583 // Fill PayLoad From JSON
584 if (responseWrapper.isEmpty()) {
585 fillToscaTemplateFromJson(responseWrapper, yamlStringWrapper, user, uploadResourceInfoWrapper.getInnerElement());
593 protected void specificResourceAuthorityValidations(final Wrapper<Response> responseWrapper,
594 final Wrapper<UploadResourceInfo> uploadResourceInfoWrapper,
595 final Wrapper<String> yamlStringWrapper, final User user,
596 final HttpServletRequest request, final String resourceInfoJsonString,
597 final ResourceAuthorityTypeEnum resourceAuthorityEnum) {
599 if (responseWrapper.isEmpty()) {
600 // UI Only Validation
601 if (!resourceAuthorityEnum.isBackEndImport()) {
602 importUIValidations(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, request, resourceInfoJsonString);
605 // User Defined Type Resources
606 if (resourceAuthorityEnum.isUserTypeResource() && !CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {
607 if (responseWrapper.isEmpty()) {
608 validatePayloadNameSpace(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, yamlStringWrapper.getInnerElement());
615 void commonGeneralValidations(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, ResourceAuthorityTypeEnum resourceAuthorityEnum, String userId,
616 String resourceInfoJsonString) {
618 if (responseWrapper.isEmpty()) {
619 validateUserExist(responseWrapper, userWrapper, userId);
622 if (responseWrapper.isEmpty()) {
623 validateUserRole(responseWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum);
626 if (responseWrapper.isEmpty()) {
627 validateAndFillResourceJson(responseWrapper, uploadResourceInfoWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum, resourceInfoJsonString);
630 if (responseWrapper.isEmpty()) {
631 validateToscaTemplatePayloadName(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
633 if (responseWrapper.isEmpty()) {
634 validateResourceType(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
639 private void validateResourceType(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
640 String resourceType = uploadResourceInfo.getResourceType();
641 if (resourceType == null || !ResourceTypeEnum.containsName(resourceType)) {
642 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
643 Response errorResponse = buildErrorResponse(responseFormat);
644 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
645 responseWrapper.setInnerElement(errorResponse);
649 private void importUIValidations(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, HttpServletRequest request, String resourceInfoJsonString) {
650 if (responseWrapper.isEmpty()) {
651 validateMD5(responseWrapper, user, resourceInfo, request, resourceInfoJsonString);
653 if (responseWrapper.isEmpty() && request != null && request.getMethod() != null && request.getMethod().equals("POST")) {
654 validateResourceDoesNotExist(responseWrapper, user, resourceInfo.getName());
658 void commonPayloadValidations(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo uploadResourceInfo) {
660 if (responseWrapper.isEmpty()) {
661 validatePayloadIsYml(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
663 if (responseWrapper.isEmpty()) {
664 validatePayloadIsTosca(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
666 if (responseWrapper.isEmpty()) {
667 validatePayloadIsNotService(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
669 if (responseWrapper.isEmpty()) {
670 validatePayloadIsSingleResource(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
675 void handleImport(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfoObject, String yamlAsString, ResourceAuthorityTypeEnum authority, boolean createNewVersion, String resourceUniqueId) {
676 ImmutablePair<Resource, ActionStatus> createOrUpdateResponse = null;
677 Response response = null;
678 Object representation = null;
679 ImmutablePair<Resource, ActionStatus> importedResourceStatus = null;
680 if (CsarValidationUtils.isCsarPayloadName(resourceInfoObject.getPayloadName())) {
681 log.debug("import resource from csar");
682 importedResourceStatus = importResourceFromUICsar(resourceInfoObject, user, resourceUniqueId);
683 } else if (!authority.isUserTypeResource()) {
684 log.debug("import normative type resource");
685 createOrUpdateResponse = resourceImportManager.importNormativeResource(yamlAsString, resourceInfoObject, user, createNewVersion, true);
687 log.debug("import user resource (not normative type)");
688 createOrUpdateResponse = resourceImportManager.importUserDefinedResource(yamlAsString, resourceInfoObject, user, false);
690 if (createOrUpdateResponse!= null){
691 importedResourceStatus = createOrUpdateResponse;
693 if(importedResourceStatus != null){
695 representation = RepresentationUtils.toRepresentation(importedResourceStatus.left);
696 } catch (IOException e) {
697 log.debug("Error while building resource representation : {}", e.getMessage(), e);
699 response = buildOkResponse(getComponentsUtils().getResponseFormat(importedResourceStatus.right), representation);
701 responseWrapper.setInnerElement(response);
704 private ImmutablePair<Resource, ActionStatus> importResourceFromUICsar(UploadResourceInfo resourceInfoObject, User user, String resourceUniqueId) {
706 Resource newResource;
707 ActionStatus actionStatus;
708 Resource resource = new Resource();
709 String payloadName = resourceInfoObject.getPayloadName();
710 fillResourceFromResourceInfoObject(resource, resourceInfoObject);
712 Map<String, byte[]> csarUIPayload = getCsarFromPayload(resourceInfoObject);
713 getAndValidateCsarYaml(csarUIPayload, resource, user, payloadName);
715 if (resourceUniqueId == null || resourceUniqueId.isEmpty()) {
716 newResource = resourceImportManager.getResourceBusinessLogic().createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, csarUIPayload, payloadName);
717 actionStatus = ActionStatus.CREATED;
719 newResource = resourceImportManager.getResourceBusinessLogic().validateAndUpdateResourceFromCsar(resource, user, csarUIPayload, payloadName, resourceUniqueId);
720 actionStatus = ActionStatus.OK;
722 return new ImmutablePair<>(newResource, actionStatus);
725 private Resource throwComponentException(ResponseFormat responseFormat) {
726 throw new ByResponseFormatComponentException(responseFormat);
729 private void getAndValidateCsarYaml(Map<String, byte[]> csarUIPayload, Resource resource, User user, String csarUUID) {
731 Either<ImmutablePair<String, String>, ResponseFormat> getToscaYamlRes = CsarValidationUtils.getToscaYaml(csarUIPayload, csarUUID, getComponentsUtils());
733 if (getToscaYamlRes.isRight()) {
734 ResponseFormat responseFormat = getToscaYamlRes.right().value();
735 log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat);
736 BeEcompErrorManager.getInstance().logBeDaoSystemError("Creating resource from CSAR: fetching CSAR with id " + csarUUID + " failed");
737 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.CREATE_RESOURCE);
738 throwComponentException(responseFormat);
740 String toscaYaml = getToscaYamlRes.left().value().getValue();
742 log.debug("checking tosca template is valid yml");
743 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
744 boolean isValid = yamlConvertor.isValidYaml(toscaYaml.getBytes());
746 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
747 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
748 throwComponentException(responseFormat);
751 log.debug("checking payload is valid tosca");
752 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaYaml);
753 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
755 if (findFirstToscaStringElement.isRight()) {
758 String defenitionVersionFound = findFirstToscaStringElement.left().value();
759 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
762 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
767 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
768 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
769 throwComponentException(responseFormat);
773 private void fillResourceFromResourceInfoObject(Resource resource, UploadResourceInfo resourceInfoObject) {
774 resourceImportManager.populateResourceMetadata(resourceInfoObject, resource);
775 fillArtifacts(resource, resourceInfoObject);
779 private void fillArtifacts(Resource resource, UploadResourceInfo resourceInfoObject) {
780 if (resource != null && resourceInfoObject != null) {
781 List<UploadArtifactInfo> artifactList = resourceInfoObject.getArtifactList();
782 if (artifactList != null) {
783 Map<String, ArtifactDefinition> artifactsHM = new HashMap<>();
784 for (UploadArtifactInfo artifact : artifactList) {
785 ArtifactDefinition artifactDef = new ArtifactDefinition();
786 artifactDef.setArtifactName(artifact.getArtifactName());
787 artifactDef.setArtifactType(artifact.getArtifactType().getType());
788 artifactDef.setDescription(artifact.getArtifactDescription());
789 artifactDef.setPayloadData(artifact.getArtifactData());
790 artifactDef.setArtifactRef(artifact.getArtifactPath());
791 artifactsHM.put(artifactDef.getArtifactName(), artifactDef);
793 resource.setArtifacts(artifactsHM);
798 private Map<String, byte[]> getCsarFromPayload(UploadResourceInfo innerElement) {
799 String csarUUID = innerElement.getPayloadName();
800 String payloadData = innerElement.getPayloadData();
801 if (payloadData == null) {
802 log.info("Failed to decode received csar {}", csarUUID);
803 throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
806 byte[] decodedPayload = Base64.decodeBase64(payloadData.getBytes(StandardCharsets.UTF_8));
807 if (decodedPayload == null) {
808 log.info("Failed to decode received csar {}", csarUUID);
809 throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
812 Map<String, byte[]> csar = null;
814 csar = ZipUtils.readZip(decodedPayload, false);
815 } catch (final ZipException e) {
816 log.info("Failed to unzip received csar {}", csarUUID, e);
818 if (MapUtils.isEmpty(csar)) {
823 void validateInputStream(final HttpServletRequest request, Wrapper<String> dataWrapper, Wrapper<ResponseFormat> errorWrapper) throws IOException {
824 InputStream inputStream = request.getInputStream();
825 byte[] bytes = IOUtils.toByteArray(inputStream);
826 if (bytes == null || bytes.length == 0) {
827 log.info("Empty body was sent.");
828 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
830 dataWrapper.setInnerElement(new String(bytes, StandardCharsets.UTF_8));
835 <T> void validateClassParse(String data, Wrapper<T> parsedClassWrapper, Supplier<Class<T>> classGen, Wrapper<ResponseFormat> errorWrapper) {
837 T parsedClass = gson.fromJson(data, classGen.get());
838 if (parsedClass == null) {
839 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
841 parsedClassWrapper.setInnerElement(parsedClass);
843 } catch (JsonSyntaxException e) {
844 log.debug("Failed to decode received {} {} to object.", classGen.get().getName(), data, e);
845 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
849 void validateComponentInstanceBusinessLogic(HttpServletRequest request, String containerComponentType, Wrapper<ComponentInstanceBusinessLogic> blWrapper, Wrapper<ResponseFormat> errorWrapper) {
850 ServletContext context = request.getSession().getServletContext();
851 ComponentInstanceBusinessLogic componentInstanceLogic = getComponentInstanceBL(context);
852 if (componentInstanceLogic == null) {
853 log.debug("Unsupported component type {}", containerComponentType);
854 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
856 blWrapper.setInnerElement(componentInstanceLogic);
860 <T> Response buildResponseFromElement(Wrapper<ResponseFormat> errorWrapper, Wrapper<T> attributeWrapper) throws IOException {
862 if (errorWrapper.isEmpty()) {
863 ObjectMapper mapper = new ObjectMapper();
864 String result = mapper.writeValueAsString(attributeWrapper.getInnerElement());
865 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
867 response = buildErrorResponse(errorWrapper.getInnerElement());
872 protected void validateXECOMPInstanceIDHeader(String instanceIdHeader, Wrapper<ResponseFormat> responseWrapper) {
873 ResponseFormat responseFormat;
874 if(StringUtils.isEmpty(instanceIdHeader) ){
875 log.debug("Missing X-ECOMP-InstanceID header");
876 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
877 responseWrapper.setInnerElement(responseFormat);
881 protected void validateHttpCspUserIdHeader(String header, Wrapper<ResponseFormat> responseWrapper) {
882 ResponseFormat responseFormat;
883 if( StringUtils.isEmpty(header)){
884 log.debug("MissingUSER_ID");
885 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_USER_ID);
886 responseWrapper.setInnerElement(responseFormat);
890 <T> Either<T, ResponseFormat> parseToObject(String json, Supplier<Class<T>> classSupplier) {
893 T object = RepresentationUtils.fromRepresentation(json, classSupplier.get());
894 return Either.left(object);
895 } catch (Exception e) {
896 log.debug("Failed to parse json to {} object", classSupplier.get().getName(), e);
897 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
898 return Either.right(responseFormat);
902 public <T> Either<List<T>, ResponseFormat> parseListOfObjects(String json, Type type) {
904 List<T> listOfObjects = gson.fromJson(json, type);
905 return Either.left(listOfObjects);
906 } catch (Exception e) {
907 log.debug("Failed to parse json to {} object", type.getClass().getName(), e);
908 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
909 return Either.right(responseFormat);
912 protected void validateNotEmptyBody(String data) {
913 if (StringUtils.isEmpty(data)) {
914 throw new ByActionStatusComponentException(ActionStatus.MISSING_BODY);