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=========================================================
21 package org.openecomp.sdc.be.servlets;
23 import com.fasterxml.jackson.databind.ObjectMapper;
24 import com.google.gson.Gson;
25 import com.google.gson.JsonSyntaxException;
26 import fj.data.Either;
27 import org.apache.commons.codec.binary.Base64;
28 import org.apache.commons.io.IOUtils;
29 import org.apache.commons.lang3.StringUtils;
30 import org.apache.commons.lang3.tuple.ImmutablePair;
31 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
32 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
33 import org.openecomp.sdc.be.components.impl.ImportUtils;
34 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
35 import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
36 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
37 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
38 import org.openecomp.sdc.be.config.BeEcompErrorManager;
39 import org.openecomp.sdc.be.dao.api.ActionStatus;
40 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
41 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
42 import org.openecomp.sdc.be.impl.ComponentsUtils;
43 import org.openecomp.sdc.be.impl.ServletUtils;
44 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
45 import org.openecomp.sdc.be.model.ArtifactDefinition;
46 import org.openecomp.sdc.be.model.Resource;
47 import org.openecomp.sdc.be.model.UploadResourceInfo;
48 import org.openecomp.sdc.be.model.User;
49 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
50 import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
51 import org.openecomp.sdc.be.user.IUserBusinessLogic;
52 import org.openecomp.sdc.be.user.Role;
53 import org.openecomp.sdc.be.utils.TypeUtils;
54 import org.openecomp.sdc.common.api.Constants;
55 import org.openecomp.sdc.common.api.UploadArtifactInfo;
56 import org.openecomp.sdc.common.datastructure.Wrapper;
57 import org.openecomp.sdc.common.log.wrappers.Logger;
58 import org.openecomp.sdc.common.util.GeneralUtility;
59 import org.openecomp.sdc.common.util.YamlToObjectConverter;
60 import org.openecomp.sdc.common.util.ZipUtil;
61 import org.openecomp.sdc.exception.ResponseFormat;
62 import org.springframework.web.context.WebApplicationContext;
63 import org.yaml.snakeyaml.Yaml;
65 import javax.servlet.ServletContext;
66 import javax.servlet.http.HttpServletRequest;
67 import javax.ws.rs.core.Response;
69 import java.lang.reflect.Type;
70 import java.nio.charset.StandardCharsets;
71 import java.util.Arrays;
72 import java.util.HashMap;
73 import java.util.List;
75 import java.util.function.Supplier;
76 import java.util.zip.ZipInputStream;
78 public abstract class AbstractValidationsServlet extends BeGenericServlet {
80 private static final Logger log = Logger.getLogger(AbstractValidationsServlet.class);
81 private static final String TOSCA_SIMPLE_YAML_PREFIX = "tosca_simple_yaml_";
82 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");
83 private static final List<String> TOSCA_YML_CSAR_VALID_SUFFIX = Arrays.asList(".yml", ".yaml", ".csar");
85 protected ServletUtils servletUtils;
87 protected ResourceImportManager resourceImportManager;
89 protected ComponentsUtils componentsUtils;
91 protected void init() {
92 initSpringFromContext();
95 private synchronized void initSpringFromContext() {
96 if (servletUtils == null) {
97 ServletContext context = servletRequest.getSession().getServletContext();
98 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context
99 .getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
100 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
101 servletUtils = webApplicationContext.getBean(ServletUtils.class);
102 resourceImportManager = webApplicationContext.getBean(ResourceImportManager.class);
103 componentsUtils = webApplicationContext.getBean(ComponentsUtils.class);
107 protected void validateResourceDoesNotExist(Wrapper<Response> responseWrapper, User user, String resourceName) {
108 if (resourceImportManager.isResourceExist(resourceName)) {
109 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESOURCE_ALREADY_EXISTS);
110 Response errorResponse = buildErrorResponse(responseFormat);
111 getComponentsUtils().auditResource(responseFormat, user, resourceName, AuditingActionEnum.IMPORT_RESOURCE);
112 responseWrapper.setInnerElement(errorResponse);
116 protected void validateUserExist(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, String userUserId) {
117 log.debug("get user {} from DB", userUserId);
119 if (userUserId == null) {
120 log.info("user userId is null");
121 Response response = returnMissingInformation(new User());
122 responseWrapper.setInnerElement(response);
126 IUserBusinessLogic userAdmin = getServletUtils().getUserAdmin();
127 Either<User, ActionStatus> eitherCreator = userAdmin.getUser(userUserId, false);
128 if (eitherCreator.isRight()) {
129 log.info("user is not listed. userId={}", userUserId);
130 User user = new User();
131 user.setUserId(userUserId);
132 Response response = returnMissingInformation(user);
133 responseWrapper.setInnerElement(response);
135 userWrapper.setInnerElement(eitherCreator.left().value());
140 protected Response returnMissingInformation(User user) {
141 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_INFORMATION);
142 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
143 return buildErrorResponse(responseFormat);
146 protected void validateDataNotNull(Wrapper<Response> responseWrapper, Object... dataParams) {
147 for (Object dataElement : dataParams) {
148 if (dataElement == null) {
149 log.info("Invalid body was received.");
150 Response response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
151 responseWrapper.setInnerElement(response);
158 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user) {
159 log.debug("validate user role");
160 if (!user.getRole().equals(Role.ADMIN.name()) && !user.getRole().equals(Role.DESIGNER.name())) {
161 log.info("user is not in appropriate role to perform action");
162 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
163 log.debug("audit before sending response");
164 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
166 Response response = buildErrorResponse(responseFormat);
167 errorResponseWrapper.setInnerElement(response);
172 protected void validateZip(Wrapper<Response> responseWrapper, File file, String payloadName) throws FileNotFoundException {
173 InputStream fileInputStream = new FileInputStream(file);
174 Map<String, byte[]> unzippedFolder = ZipUtil.readZip(new ZipInputStream(fileInputStream));
175 if (payloadName == null || payloadName.isEmpty() || !unzippedFolder.containsKey(payloadName)) {
176 log.info("Invalid json was received. payloadName should be yml file name");
177 Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
178 responseWrapper.setInnerElement(errorResponse);
182 protected void validateCsar(Wrapper<Response> responseWrapper, File file, String payloadName) throws FileNotFoundException {
183 InputStream fileInputStream = new FileInputStream(file);
184 Map<String, byte[]> unzippedFolder = ZipUtil.readZip(new ZipInputStream(fileInputStream));
185 if (payloadName == null || payloadName.isEmpty() || unzippedFolder.isEmpty()) {
186 log.info("Invalid json was received. payloadName should be yml file name");
187 Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
188 responseWrapper.setInnerElement(errorResponse);
193 protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) throws FileNotFoundException {
194 extractZipContents(yamlStringWrapper, file);
197 public static void extractZipContents(Wrapper<String> yamlStringWrapper, File file) throws FileNotFoundException {
198 InputStream fileInputStream = new FileInputStream(file);
199 Map<String, byte[]> unzippedFolder = ZipUtil.readZip(new ZipInputStream(fileInputStream));
200 String ymlName = unzippedFolder.keySet().iterator().next();
201 fillToscaTemplateFromZip(yamlStringWrapper, ymlName, file);
204 private static void fillToscaTemplateFromZip(Wrapper<String> yamlStringWrapper, String payloadName, File file) throws FileNotFoundException {
205 InputStream fileInputStream = new FileInputStream(file);
206 Map<String, byte[]> unzippedFolder = ZipUtil.readZip(new ZipInputStream(fileInputStream));
207 byte[] yamlFileInBytes = unzippedFolder.get(payloadName);
208 String yamlAsString = new String(yamlFileInBytes, StandardCharsets.UTF_8);
209 log.debug("received yaml: {}", yamlAsString);
210 yamlStringWrapper.setInnerElement(yamlAsString);
213 protected void fillPayloadDataFromFile(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfoWrapper, File file) {
214 try(InputStream fileInputStream = new FileInputStream(file)){
216 byte [] data = new byte[(int)file.length()];
217 if( fileInputStream.read(data) == -1){
218 log.info("Invalid json was received.");
219 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
221 Response errorResp = buildErrorResponse(responseFormat);
222 responseWrapper.setInnerElement(errorResp);
224 String payloadData = Base64.encodeBase64String(data);
225 uploadResourceInfoWrapper.setPayloadData(payloadData);
229 } catch (IOException e) {
230 log.info("Invalid json was received or Error while closing input Stream.");
231 log.debug("Invalid json was received or Error while closing input Stream. {}", e.getMessage(), e);
232 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
234 Response errorResp = buildErrorResponse(responseFormat);
235 responseWrapper.setInnerElement(errorResp);
240 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user, ResourceAuthorityTypeEnum resourceAuthority) {
241 log.debug("validate user role");
242 if (resourceAuthority == ResourceAuthorityTypeEnum.NORMATIVE_TYPE_BE) {
243 if (!user.getRole().equals(Role.ADMIN.name())) {
244 log.info("user is not in appropriate role to perform action");
245 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
246 log.debug("audit before sending response");
247 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
249 Response response = buildErrorResponse(responseFormat);
250 errorResponseWrapper.setInnerElement(response);
253 validateUserRole(errorResponseWrapper, user);
258 protected void validateAndFillResourceJson(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, User user, ResourceAuthorityTypeEnum resourceAuthorityEnum, String resourceInfo) {
261 log.debug("The received json is {}", resourceInfo);
262 UploadResourceInfo resourceInfoObject = gson.fromJson(resourceInfo, UploadResourceInfo.class);
263 if (resourceInfoObject == null) {
266 if (!resourceAuthorityEnum.isBackEndImport()) {
267 isValid = resourceInfoObject.getPayloadName() != null && !resourceInfoObject.getPayloadName().isEmpty();
268 //only resource name is checked
272 uploadResourceInfoWrapper.setInnerElement(resourceInfoObject);
275 } catch (JsonSyntaxException e) {
276 log.debug("Invalid json was received. {}", e.getMessage(), e);
281 log.info("Invalid json was received.");
282 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
283 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
284 Response errorResp = buildErrorResponse(responseFormat);
285 responseWrapper.setInnerElement(errorResp);
289 protected void validateAuthorityType(Wrapper<Response> responseWrapper, String authorityType) {
290 log.debug("The received authority type is {}", authorityType);
291 ResourceAuthorityTypeEnum authorityTypeEnum = ResourceAuthorityTypeEnum.findByUrlPath(authorityType);
292 if (authorityTypeEnum == null) {
293 log.info("Invalid authority type was received.");
294 Response errorResp = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
295 responseWrapper.setInnerElement(errorResp);
299 public ServletUtils getServletUtils() {
300 initSpringFromContext();
304 public Gson getGson() {
305 return getServletUtils().getGson();
308 public ComponentsUtils getComponentsUtils() {
309 return getServletUtils().getComponentsUtils();
312 protected void validatePayloadIsTosca(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
313 log.debug("checking payload is valid tosca");
315 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
316 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
318 if (findFirstToscaStringElement.isRight()) {
321 String defenitionVersionFound = findFirstToscaStringElement.left().value();
322 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
325 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
330 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
331 Response errorResponse = buildErrorResponse(responseFormat);
332 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
333 responseWrapper.setInnerElement(errorResponse);
338 protected void validatePayloadIsYml(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaTamplatePayload) {
339 log.debug("checking tosca template is valid yml");
340 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
341 boolean isYamlValid = yamlConvertor.isValidYaml(toscaTamplatePayload.getBytes());
343 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
344 Response errorResponse = buildErrorResponse(responseFormat);
345 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
346 responseWrapper.setInnerElement(errorResponse);
350 protected void validatePayloadNameSpace(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, String toscaPayload) {
352 String nameSpace = "";
353 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
354 Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
355 if (toscaElement.isRight() || toscaElement.left().value().size() != 1) {
358 nameSpace = toscaElement.left().value().keySet().iterator().next();
359 isValid = nameSpace.startsWith(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX);
362 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_NAMESPACE);
363 Response errorResponse = buildErrorResponse(responseFormat);
364 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
365 responseWrapper.setInnerElement(errorResponse);
367 String str1 = nameSpace.substring(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX.length());
368 String[] findTypes = str1.split("\\.");
369 if (ResourceTypeEnum.containsName(findTypes[0].toUpperCase())) {
370 String type = findTypes[0].toUpperCase();
371 resourceInfo.setResourceType(type);
373 resourceInfo.setResourceType(ResourceTypeEnum.VFC.name());
379 protected void validatePayloadIsSingleResource(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
380 log.debug("checking payload contains single resource");
382 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
383 Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
384 if (toscaElement.isRight()) {
387 isValid = toscaElement.left().value().size() == 1;
391 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_SINGLE_RESOURCE);
392 Response errorResponse = buildErrorResponse(responseFormat);
393 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
394 responseWrapper.setInnerElement(errorResponse);
399 protected void validatePayloadIsNotService(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaPayload) {
400 log.debug("checking payload is not a tosca service");
401 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
402 Either<Object, ResultStatusEnum> toscaElement = ImportUtils.findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL);
404 if (toscaElement.isLeft()) {
405 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_RESOURCE_TOSCA_TEMPLATE);
406 Response errorResponse = buildErrorResponse(responseFormat);
407 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
408 responseWrapper.setInnerElement(errorResponse);
413 protected void validateToscaTemplatePayloadName(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
414 String toscaTemplatePayloadName = uploadResourceInfo.getPayloadName();
415 boolean isValidSuffix = false;
416 if (toscaTemplatePayloadName != null && !toscaTemplatePayloadName.isEmpty()) {
417 for (String validSuffix : TOSCA_YML_CSAR_VALID_SUFFIX) {
418 isValidSuffix = isValidSuffix || toscaTemplatePayloadName.toLowerCase().endsWith(validSuffix);
421 if (!isValidSuffix) {
422 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_FILE_EXTENSION);
423 Response errorResponse = buildErrorResponse(responseFormat);
424 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
425 responseWrapper.setInnerElement(errorResponse);
430 protected void validateMD5(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfo, HttpServletRequest request, String resourceInfoJsonString) {
432 String recievedMD5 = request.getHeader(Constants.MD5_HEADER);
433 if (recievedMD5 == null) {
436 String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(resourceInfoJsonString);
437 isValid = calculateMD5.equals(recievedMD5);
440 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_CHECKSUM);
441 Response errorResponse = buildErrorResponse(responseFormat);
442 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
443 responseWrapper.setInnerElement(errorResponse);
447 protected void validateComponentType(Wrapper<Response> responseWrapper, Wrapper<ComponentTypeEnum> componentTypeWrapper, String componentType) {
449 if (componentType == null) {
452 if (ComponentTypeEnum.RESOURCE_PARAM_NAME.equalsIgnoreCase(componentType)) {
454 componentTypeWrapper.setInnerElement(ComponentTypeEnum.RESOURCE);
455 } else if (ComponentTypeEnum.SERVICE_PARAM_NAME.equalsIgnoreCase(componentType)) {
457 componentTypeWrapper.setInnerElement(ComponentTypeEnum.SERVICE);
463 log.debug("Invalid componentType:{}", componentType);
464 responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, componentType)));
468 protected Either<ComponentTypeEnum, ResponseFormat> convertToComponentType(String componentType) {
469 Wrapper<Response> errorWrapper = new Wrapper<>();
470 Wrapper<ComponentTypeEnum> componentWrapper = new Wrapper<>();
471 validateComponentType(errorWrapper, componentWrapper, componentType);
472 return errorWrapper.isEmpty() ? Either.left(componentWrapper.getInnerElement()) : Either.right(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
475 protected void fillToscaTemplateFromJson(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo resourceInfo) {
476 if (resourceInfo.getPayloadData() == null || resourceInfo.getPayloadData().isEmpty()) {
477 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_PAYLOAD);
478 Response errorResponse = buildErrorResponse(responseFormat);
479 getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
480 responseWrapper.setInnerElement(errorResponse);
482 String toscaPayload = resourceInfo.getPayloadData();
483 String decodedPayload = new String(Base64.decodeBase64(toscaPayload));
484 yamlStringWrapper.setInnerElement(decodedPayload);
489 protected void fillPayload(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, String resourceInfoJsonString, ResourceAuthorityTypeEnum resourceAuthorityEnum,
490 File file) throws FileNotFoundException {
492 if (responseWrapper.isEmpty()) {
493 if (resourceAuthorityEnum.isBackEndImport()) {
494 // PrePayload Validations
495 if (responseWrapper.isEmpty()) {
496 validateDataNotNull(responseWrapper, file, resourceInfoJsonString);
498 if(!resourceAuthorityEnum.equals(ResourceAuthorityTypeEnum.CSAR_TYPE_BE)){
499 if (responseWrapper.isEmpty()) {
500 validateZip(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
503 // Fill PayLoad From File
504 if (responseWrapper.isEmpty()) {
505 fillToscaTemplateFromZip(yamlStringWrapper, uploadResourceInfoWrapper.getInnerElement().getPayloadName(), file);
509 if (responseWrapper.isEmpty()) {
510 validateCsar(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
513 // Fill PayLoad From File
514 if (responseWrapper.isEmpty()) {
515 fillPayloadDataFromFile(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), file);
521 // Fill PayLoad From JSON
522 if (responseWrapper.isEmpty()) {
523 fillToscaTemplateFromJson(responseWrapper, yamlStringWrapper, user, uploadResourceInfoWrapper.getInnerElement());
531 protected void specificResourceAuthorityValidations(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, HttpServletRequest request, String resourceInfoJsonString,
532 ResourceAuthorityTypeEnum resourceAuthorityEnum) throws FileNotFoundException {
534 if (responseWrapper.isEmpty()) {
535 // UI Only Validation
536 if (!resourceAuthorityEnum.isBackEndImport()) {
537 importUIValidations(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, request, resourceInfoJsonString);
540 // User Defined Type Resources
541 if (resourceAuthorityEnum.isUserTypeResource() && !CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {
542 if (responseWrapper.isEmpty()) {
543 validatePayloadNameSpace(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, yamlStringWrapper.getInnerElement());
550 protected void commonGeneralValidations(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, ResourceAuthorityTypeEnum resourceAuthorityEnum, String userUserId,
551 String resourceInfoJsonString) {
553 if (responseWrapper.isEmpty()) {
554 validateUserExist(responseWrapper, userWrapper, userUserId);
557 if (responseWrapper.isEmpty()) {
558 validateUserRole(responseWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum);
561 if (responseWrapper.isEmpty()) {
562 validateAndFillResourceJson(responseWrapper, uploadResourceInfoWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum, resourceInfoJsonString);
565 if (responseWrapper.isEmpty()) {
566 validateToscaTemplatePayloadName(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
568 if (responseWrapper.isEmpty()) {
569 validateResourceType(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
574 private void validateResourceType(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
575 String resourceType = uploadResourceInfo.getResourceType();
576 if (resourceType == null || !ResourceTypeEnum.containsName(resourceType)) {
577 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
578 Response errorResponse = buildErrorResponse(responseFormat);
579 getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
580 responseWrapper.setInnerElement(errorResponse);
584 protected void importUIValidations(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, HttpServletRequest request, String resourceInfoJsonString) {
585 if (responseWrapper.isEmpty()) {
586 validateMD5(responseWrapper, user, resourceInfo, request, resourceInfoJsonString);
588 if (responseWrapper.isEmpty() && request != null && request.getMethod() != null && request.getMethod().equals("POST")) {
589 validateResourceDoesNotExist(responseWrapper, user, resourceInfo.getName());
593 protected void commonPayloadValidations(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo uploadResourceInfo) {
595 if (responseWrapper.isEmpty()) {
596 validatePayloadIsYml(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
598 if (responseWrapper.isEmpty()) {
599 validatePayloadIsTosca(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
601 if (responseWrapper.isEmpty()) {
602 validatePayloadIsNotService(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
604 if (responseWrapper.isEmpty()) {
605 validatePayloadIsSingleResource(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
610 protected void handleImport(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfoObject, String yamlAsString, ResourceAuthorityTypeEnum authority, boolean createNewVersion, String resourceUniqueId) {
611 Either<ImmutablePair<Resource, ActionStatus>, ResponseFormat> createOrUpdateResponse = null;
612 Response response = null;
613 Object representation = null;
614 ImmutablePair<Resource, ActionStatus> importedResourceStatus = null;
615 if (CsarValidationUtils.isCsarPayloadName(resourceInfoObject.getPayloadName())) {
616 log.debug("import resource from csar");
617 importedResourceStatus = importResourceFromUICsar(resourceInfoObject, user, resourceUniqueId);
618 } else if (!authority.isUserTypeResource()) {
619 log.debug("import normative type resource");
620 createOrUpdateResponse = resourceImportManager.importNormativeResource(yamlAsString, resourceInfoObject, user, createNewVersion, true);
622 log.debug("import user resource (not normative type)");
623 createOrUpdateResponse = resourceImportManager.importUserDefinedResource(yamlAsString, resourceInfoObject, user, false);
625 if (createOrUpdateResponse!= null){
626 if(createOrUpdateResponse.isRight()){
627 response = buildErrorResponse(createOrUpdateResponse.right().value());
629 importedResourceStatus = createOrUpdateResponse.left().value();
632 if(importedResourceStatus != null){
634 representation = RepresentationUtils.toRepresentation(importedResourceStatus.left);
635 } catch (IOException e) {
636 log.debug("Error while building resource representation : {}", e.getMessage(), e);
638 response = buildOkResponse(getComponentsUtils().getResponseFormat(importedResourceStatus.right), representation);
640 responseWrapper.setInnerElement(response);
643 private ImmutablePair<Resource, ActionStatus> importResourceFromUICsar(UploadResourceInfo resourceInfoObject, User user, String resourceUniqueId) {
645 Resource newResource;
646 ImmutablePair<Resource, ActionStatus> result = null;
647 ActionStatus actionStatus;
648 Resource resource = new Resource();
649 String payloadName = resourceInfoObject.getPayloadName();
650 fillResourceFromResourceInfoObject(resource, resourceInfoObject);
652 Either<Map<String, byte[]>, ResponseFormat> csarUIPayloadRes = getCsarFromPayload(resourceInfoObject);
653 if (csarUIPayloadRes.isRight()) {
654 throw new ComponentException(csarUIPayloadRes.right().value());
656 Map<String, byte[]> csarUIPayload = csarUIPayloadRes.left().value();
658 getAndValidateCsarYaml(csarUIPayload, resource, user, payloadName);
660 if (resourceUniqueId == null || resourceUniqueId.isEmpty()) {
661 newResource = resourceImportManager.getResourceBusinessLogic().createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, csarUIPayload, payloadName);
662 actionStatus = ActionStatus.CREATED;
664 newResource = resourceImportManager.getResourceBusinessLogic().validateAndUpdateResourceFromCsar(resource, user, csarUIPayload, payloadName, resourceUniqueId);
665 actionStatus = ActionStatus.OK;
667 return new ImmutablePair<>(newResource, actionStatus);
670 private Resource throwComponentException(ResponseFormat responseFormat) {
671 throw new ComponentException(responseFormat);
674 private void getAndValidateCsarYaml(Map<String, byte[]> csarUIPayload, Resource resource, User user, String csarUUID) {
676 Either<ImmutablePair<String, String>, ResponseFormat> getToscaYamlRes = CsarValidationUtils.getToscaYaml(csarUIPayload, csarUUID, getComponentsUtils());
678 if (getToscaYamlRes.isRight()) {
679 ResponseFormat responseFormat = getToscaYamlRes.right().value();
680 log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat);
681 BeEcompErrorManager.getInstance().logBeDaoSystemError("Creating resource from CSAR: fetching CSAR with id " + csarUUID + " failed");
682 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.CREATE_RESOURCE);
683 throwComponentException(responseFormat);
685 String toscaYaml = getToscaYamlRes.left().value().getValue();
687 log.debug("checking tosca template is valid yml");
688 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
689 boolean isValid = yamlConvertor.isValidYaml(toscaYaml.getBytes());
691 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
692 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
693 throwComponentException(responseFormat);
696 log.debug("checking payload is valid tosca");
697 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaYaml);
698 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
700 if (findFirstToscaStringElement.isRight()) {
703 String defenitionVersionFound = findFirstToscaStringElement.left().value();
704 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
707 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
712 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
713 getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
714 throwComponentException(responseFormat);
718 private void fillResourceFromResourceInfoObject(Resource resource, UploadResourceInfo resourceInfoObject) {
719 resourceImportManager.populateResourceMetadata(resourceInfoObject, resource);
720 fillArtifacts(resource, resourceInfoObject);
724 private void fillArtifacts(Resource resource, UploadResourceInfo resourceInfoObject) {
725 if (resource != null && resourceInfoObject != null) {
726 List<UploadArtifactInfo> artifactList = resourceInfoObject.getArtifactList();
727 if (artifactList != null) {
728 Map<String, ArtifactDefinition> artifactsHM = new HashMap<>();
729 for (UploadArtifactInfo artifact : artifactList) {
730 ArtifactDefinition artifactDef = new ArtifactDefinition();
731 artifactDef.setArtifactName(artifact.getArtifactName());
732 artifactDef.setArtifactType(artifact.getArtifactType().getType());
733 artifactDef.setDescription(artifact.getArtifactDescription());
734 artifactDef.setPayloadData(artifact.getArtifactData());
735 artifactDef.setArtifactRef(artifact.getArtifactPath());
736 artifactsHM.put(artifactDef.getArtifactName(), artifactDef);
738 resource.setArtifacts(artifactsHM);
743 private Either<Map<String, byte[]>, ResponseFormat> getCsarFromPayload(UploadResourceInfo innerElement) {
744 String csarUUID = innerElement.getPayloadName();
745 String payloadData = innerElement.getPayloadData();
746 if (payloadData == null) {
747 log.info("Failed to decode received csar", csarUUID);
748 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_NOT_FOUND, csarUUID));
751 byte[] decodedPayload = Base64.decodeBase64(payloadData.getBytes(StandardCharsets.UTF_8));
752 if (decodedPayload == null) {
753 log.info("Failed to decode received csar", csarUUID);
754 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_NOT_FOUND, csarUUID));
757 Map<String, byte[]> csar = ZipUtil.readZip(decodedPayload);
759 log.info("Failed to unzip received csar", csarUUID);
760 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID, csarUUID));
762 return Either.left(csar);
765 protected void validateInputStream(final HttpServletRequest request, Wrapper<String> dataWrapper, Wrapper<ResponseFormat> errorWrapper) throws IOException {
766 InputStream inputStream = request.getInputStream();
767 byte[] bytes = IOUtils.toByteArray(inputStream);
768 if (bytes == null || bytes.length == 0) {
769 log.info("Empty body was sent.");
770 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
772 dataWrapper.setInnerElement(new String(bytes, StandardCharsets.UTF_8));
777 protected <T> void validateClassParse(String data, Wrapper<T> parsedClassWrapper, Supplier<Class<T>> classGen, Wrapper<ResponseFormat> errorWrapper) {
779 T parsedClass = gson.fromJson(data, classGen.get());
780 if (parsedClass == null) {
781 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
783 parsedClassWrapper.setInnerElement(parsedClass);
785 } catch (JsonSyntaxException e) {
786 log.debug("Failed to decode received {} {} to object.", classGen.get().getName(), data, e);
787 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
791 protected void validateComponentInstanceBusinessLogic(HttpServletRequest request, String containerComponentType, Wrapper<ComponentInstanceBusinessLogic> blWrapper, Wrapper<ResponseFormat> errorWrapper) {
792 ServletContext context = request.getSession().getServletContext();
794 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
795 ComponentInstanceBusinessLogic componentInstanceLogic = getComponentInstanceBL(context);
796 if (componentInstanceLogic == null) {
797 log.debug("Unsupported component type {}", containerComponentType);
798 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
800 blWrapper.setInnerElement(componentInstanceLogic);
804 protected <T> Response buildResponseFromElement(Wrapper<ResponseFormat> errorWrapper, Wrapper<T> attributeWrapper) throws IOException {
806 if (errorWrapper.isEmpty()) {
807 ObjectMapper mapper = new ObjectMapper();
808 String result = mapper.writeValueAsString(attributeWrapper.getInnerElement());
809 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
811 response = buildErrorResponse(errorWrapper.getInnerElement());
816 protected void validateXECOMPInstanceIDHeader(String instanceIdHeader, Wrapper<ResponseFormat> responseWrapper) {
817 ResponseFormat responseFormat;
818 if(StringUtils.isEmpty(instanceIdHeader) ){
819 log.debug("Missing X-ECOMP-InstanceID header");
820 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
821 responseWrapper.setInnerElement(responseFormat);
825 protected void validateHttpCspUserIdHeader(String header, Wrapper<ResponseFormat> responseWrapper) {
826 ResponseFormat responseFormat;
827 if( StringUtils.isEmpty(header)){
828 log.debug("MissingUSER_ID");
829 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_USER_ID);
830 responseWrapper.setInnerElement(responseFormat);
835 * Convert json to Object object
837 * @param classSupplier
841 public <T> Either<T, ResponseFormat> parseToObject(String json, Supplier<Class<T>> classSupplier) {
844 T object = RepresentationUtils.fromRepresentation(json, classSupplier.get());
845 return Either.left(object);
846 } catch (Exception e) {
847 log.debug("Failed to parse json to {} object", classSupplier.get().getName(), e);
848 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
849 return Either.right(responseFormat);
854 * Convert json to Object object
860 public <T> Either<List<T>, ResponseFormat> parseListOfObjects(String json, Type type) {
862 List<T> listOfObjects = gson.fromJson(json, type);
863 return Either.left(listOfObjects);
864 } catch (Exception e) {
865 log.debug("Failed to parse json to {} object", type.getClass().getName(), e);
866 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
867 return Either.right(responseFormat);