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;
24 import java.io.FileInputStream;
25 import java.io.FileNotFoundException;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.nio.charset.StandardCharsets;
29 import java.util.EnumMap;
30 import java.util.HashMap;
31 import java.util.List;
33 import java.util.function.Supplier;
34 import java.util.zip.ZipInputStream;
36 import javax.annotation.Resource;
37 import javax.servlet.ServletContext;
38 import javax.servlet.http.HttpServletRequest;
39 import javax.ws.rs.core.Response;
41 import org.apache.commons.codec.binary.Base64;
42 import org.apache.commons.io.IOUtils;
43 import org.apache.commons.lang3.tuple.ImmutablePair;
44 import org.codehaus.jackson.map.ObjectMapper;
45 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
46 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
47 import org.openecomp.sdc.be.components.impl.ImportUtils;
48 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
49 import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
50 import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaTagNamesEnum;
51 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
52 import org.openecomp.sdc.be.config.BeEcompErrorManager;
53 import org.openecomp.sdc.be.dao.api.ActionStatus;
54 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
55 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
56 import org.openecomp.sdc.be.impl.ComponentsUtils;
57 import org.openecomp.sdc.be.impl.ServletUtils;
58 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
59 import org.openecomp.sdc.be.model.ArtifactDefinition;
60 import org.openecomp.sdc.be.model.UploadResourceInfo;
61 import org.openecomp.sdc.be.model.User;
62 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
63 import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
64 import org.openecomp.sdc.be.user.IUserBusinessLogic;
65 import org.openecomp.sdc.be.user.Role;
66 import org.openecomp.sdc.common.api.Constants;
67 import org.openecomp.sdc.common.api.UploadArtifactInfo;
68 import org.openecomp.sdc.common.datastructure.AuditingFieldsKeysEnum;
69 import org.openecomp.sdc.common.datastructure.Wrapper;
70 import org.openecomp.sdc.common.util.GeneralUtility;
71 import org.openecomp.sdc.common.util.YamlToObjectConverter;
72 import org.openecomp.sdc.common.util.ZipUtil;
73 import org.openecomp.sdc.exception.ResponseFormat;
74 import org.slf4j.Logger;
75 import org.springframework.beans.factory.annotation.Autowired;
76 import org.springframework.web.context.WebApplicationContext;
77 import org.yaml.snakeyaml.Yaml;
79 import com.google.gson.Gson;
80 import com.google.gson.JsonSyntaxException;
82 import fj.data.Either;
84 public abstract class AbstractValidationsServlet extends BeGenericServlet {
87 private ServletUtils servletUtils;
90 private ResourceImportManager resourceImportManager;
93 protected ComponentsUtils componentsUtils;
95 private static final Object LOCK = new Object();
96 private Logger log = null;
98 protected void init(Logger log) {
100 initSpringFromContext();
104 private void initLog(Logger log) {
105 if (this.log == null) {
106 synchronized (LOCK) {
107 if (this.log == null) {
115 private void initSpringFromContext() {
116 if (servletUtils == null) {
117 synchronized (LOCK) {
118 if (servletUtils == null) {
119 ServletContext context = servletRequest.getSession().getServletContext();
120 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
121 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
122 servletUtils = webApplicationContext.getBean(ServletUtils.class);
123 resourceImportManager = webApplicationContext.getBean(ResourceImportManager.class);
129 protected void validateResourceDoesNotExist(Wrapper<Response> responseWrapper, User user, String resourceName) {
130 if (resourceImportManager.isResourceExist(resourceName)) {
131 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESOURCE_ALREADY_EXISTS);
132 Response errorResponse = buildErrorResponse(responseFormat);
133 EnumMap<AuditingFieldsKeysEnum, Object> additionalParam = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
134 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceName);
135 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, additionalParam);
136 responseWrapper.setInnerElement(errorResponse);
140 protected void validateUserExist(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, String userId) {
141 log.debug("get user {} from DB", userId);
143 if (userId == null) {
144 log.info("user userId is null");
145 Response response = returnMissingInformation(new User());
146 responseWrapper.setInnerElement(response);
150 IUserBusinessLogic userAdmin = getServletUtils().getUserAdmin();
151 Either<User, ActionStatus> eitherCreator = userAdmin.getUser(userId, false);
152 if (eitherCreator.isRight()) {
153 log.info("user is not listed. userId={}", userId);
154 User user = new User();
155 user.setUserId(userId);
156 Response response = returnMissingInformation(user);
157 responseWrapper.setInnerElement(response);
159 userWrapper.setInnerElement(eitherCreator.left().value());
164 protected Response returnMissingInformation(User user) {
165 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_INFORMATION);
166 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, null);
167 return buildErrorResponse(responseFormat);
170 protected void validateDataNotNull(Wrapper<Response> responseWrapper, Object... dataParams) {
171 for (Object dataElement : dataParams) {
172 if (dataElement == null) {
173 log.info("Invalid body was received.");
174 Response response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
175 responseWrapper.setInnerElement(response);
182 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user) {
183 log.debug("validate user role");
184 if (!user.getRole().equals(Role.ADMIN.name()) && !user.getRole().equals(Role.DESIGNER.name())) {
185 log.info("user is not in appropriate role to perform action");
186 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
187 log.debug("audit before sending response");
188 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, null);
190 Response response = buildErrorResponse(responseFormat);
191 errorResponseWrapper.setInnerElement(response);
196 protected void validateZip(Wrapper<Response> responseWrapper, File file, String payloadName) throws FileNotFoundException {
197 InputStream fileInputStream = new FileInputStream(file);
198 Map<String, byte[]> unzippedFolder = ZipUtil.readZip(new ZipInputStream(fileInputStream));
199 if (payloadName == null || payloadName.isEmpty() || !unzippedFolder.containsKey(payloadName)) {
200 log.info("Invalid json was received. payloadName should be yml file name");
201 Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
202 responseWrapper.setInnerElement(errorResponse);
207 protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) throws FileNotFoundException {
208 InputStream fileInputStream = new FileInputStream(file);
209 Map<String, byte[]> unzippedFolder = ZipUtil.readZip(new ZipInputStream(fileInputStream));
210 String ymlName = unzippedFolder.keySet().iterator().next();
211 fillToscaTemplateFromZip(yamlStringWrapper, ymlName, file);
214 protected void fillToscaTemplateFromZip(Wrapper<String> yamlStringWrapper, String payloadName, File file) throws FileNotFoundException {
215 InputStream fileInputStream = new FileInputStream(file);
216 Map<String, byte[]> unzippedFolder = ZipUtil.readZip(new ZipInputStream(fileInputStream));
217 byte[] yamlFileInBytes = unzippedFolder.get(payloadName);
218 String yamlAsString = new String(yamlFileInBytes, StandardCharsets.UTF_8);
219 log.debug("received yaml: {}", yamlAsString);
220 yamlStringWrapper.setInnerElement(yamlAsString);
223 protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user, ResourceAuthorityTypeEnum resourceAuthority) {
224 log.debug("validate user role");
225 if (resourceAuthority == ResourceAuthorityTypeEnum.NORMATIVE_TYPE_BE) {
226 if (!user.getRole().equals(Role.ADMIN.name())) {
227 log.info("user is not in appropriate role to perform action");
228 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
229 log.debug("audit before sending response");
230 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, null);
232 Response response = buildErrorResponse(responseFormat);
233 errorResponseWrapper.setInnerElement(response);
236 validateUserRole(errorResponseWrapper, user);
241 protected void validateAndFillResourceJson(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, User user, ResourceAuthorityTypeEnum resourceAuthorityEnum, String resourceInfo) {
244 log.debug("The received json is {}", resourceInfo);
245 UploadResourceInfo resourceInfoObject = gson.fromJson(resourceInfo, UploadResourceInfo.class);
246 if (resourceInfoObject == null) {
249 if (!resourceAuthorityEnum.isBackEndImport()) {
250 isValid = resourceInfoObject.getPayloadName() != null && !resourceInfoObject.getPayloadName().isEmpty();
251 // TODO Tal only resource name is checked
255 uploadResourceInfoWrapper.setInnerElement(resourceInfoObject);
258 } catch (JsonSyntaxException e) {
263 log.info("Invalid json was received.");
264 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
265 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, null);
266 Response errorResp = buildErrorResponse(responseFormat);
267 responseWrapper.setInnerElement(errorResp);
271 protected void validateAuthorityType(Wrapper<Response> responseWrapper, String authorityType) {
272 log.debug("The received authority type is {}", authorityType);
273 ResourceAuthorityTypeEnum authorityTypeEnum = ResourceAuthorityTypeEnum.findByUrlPath(authorityType);
274 if (authorityTypeEnum == null) {
275 log.info("Invalid authority type was received.");
276 Response errorResp = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
277 responseWrapper.setInnerElement(errorResp);
281 public ServletUtils getServletUtils() {
282 initSpringFromContext();
286 public Gson getGson() {
287 return getServletUtils().getGson();
290 public ComponentsUtils getComponentsUtils() {
291 return getServletUtils().getComponentsUtils();
294 protected void validatePayloadIsTosca(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
295 log.debug("checking payload is valid tosca");
297 String heatDecodedPayload = (GeneralUtility.isBase64Encoded(toscaPayload)) ? new String(Base64.decodeBase64(toscaPayload)) : toscaPayload;
298 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(heatDecodedPayload);
299 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, ToscaTagNamesEnum.TOSCA_VERSION);
301 if (findFirstToscaStringElement.isRight()) {
304 String defenitionVersionFound = findFirstToscaStringElement.left().value();
305 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
308 isValid = ImportUtils.Constants.TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
313 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
314 Response errorResponse = buildErrorResponse(responseFormat);
315 EnumMap<AuditingFieldsKeysEnum, Object> additionalParam = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
316 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, uploadResourceInfo.getName());
317 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, additionalParam);
318 responseWrapper.setInnerElement(errorResponse);
323 protected void validatePayloadIsYml(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaTamplatePayload) {
324 log.debug("checking tosca template is valid yml");
325 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
326 boolean isYamlValid = yamlConvertor.isValidYaml(toscaTamplatePayload.getBytes());
328 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
329 Response errorResponse = buildErrorResponse(responseFormat);
330 EnumMap<AuditingFieldsKeysEnum, Object> additionalParam = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
331 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, uploadResourceInfo.getName());
332 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, additionalParam);
333 responseWrapper.setInnerElement(errorResponse);
337 protected void validatePayloadNameSpace(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, String toscaPayload) {
339 String nameSpace = "";
341 String heatDecodedPayload = (GeneralUtility.isBase64Encoded(toscaPayload)) ? new String(Base64.decodeBase64(toscaPayload)) : toscaPayload;
342 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(heatDecodedPayload);
343 Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, ToscaTagNamesEnum.NODE_TYPES);
344 if (toscaElement.isRight() || toscaElement.left().value().size() != 1) {
347 nameSpace = toscaElement.left().value().keySet().iterator().next();
348 isValid = nameSpace.startsWith(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX);
351 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_NAMESPACE);
352 Response errorResponse = buildErrorResponse(responseFormat);
353 EnumMap<AuditingFieldsKeysEnum, Object> additionalParam = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
354 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceInfo.getName());
355 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, additionalParam);
356 responseWrapper.setInnerElement(errorResponse);
358 String str1 = nameSpace.substring(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX.length());
359 String[] findTypes = str1.split("\\.");
360 if (ResourceTypeEnum.contains(findTypes[0].toUpperCase())) {
361 String type = findTypes[0].toUpperCase();
362 resourceInfo.setResourceType(type);
364 resourceInfo.setResourceType(ResourceTypeEnum.VFC.name());
370 protected void validatePayloadIsSingleResource(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
371 log.debug("checking payload contains single resource");
373 String heatDecodedPayload = (GeneralUtility.isBase64Encoded(toscaPayload)) ? new String(Base64.decodeBase64(toscaPayload)) : toscaPayload;
374 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(heatDecodedPayload);
375 Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, ToscaTagNamesEnum.NODE_TYPES);
376 if (toscaElement.isRight()) {
379 isValid = toscaElement.left().value().size() == 1;
383 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_SINGLE_RESOURCE);
384 Response errorResponse = buildErrorResponse(responseFormat);
385 EnumMap<AuditingFieldsKeysEnum, Object> additionalParam = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
386 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, uploadResourceInfo.getName());
387 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, additionalParam);
388 responseWrapper.setInnerElement(errorResponse);
393 protected void validatePayloadIsNotService(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaPayload) {
394 log.debug("checking payload is not a tosca service");
395 String heatDecodedPayload = (GeneralUtility.isBase64Encoded(toscaPayload)) ? new String(Base64.decodeBase64(toscaPayload)) : toscaPayload;
396 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(heatDecodedPayload);
397 Either<Object, ResultStatusEnum> toscaElement = ImportUtils.findToscaElement(mappedToscaTemplate, ToscaTagNamesEnum.TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL);
399 if (toscaElement.isLeft()) {
400 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_RESOURCE_TOSCA_TEMPLATE);
401 Response errorResponse = buildErrorResponse(responseFormat);
402 EnumMap<AuditingFieldsKeysEnum, Object> additionalParam = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
403 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, uploadResourceInfo.getName());
404 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, additionalParam);
405 responseWrapper.setInnerElement(errorResponse);
410 protected void validatePayloadIsTopologyTemplate(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaPayload) {
411 log.debug("checking payload is a tosca topology template");
412 String heatDecodedPayload = (GeneralUtility.isBase64Encoded(toscaPayload)) ? new String(Base64.decodeBase64(toscaPayload)) : toscaPayload;
413 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(heatDecodedPayload);
414 Either<Object, ResultStatusEnum> toscaElement = ImportUtils.findToscaElement(mappedToscaTemplate, ToscaTagNamesEnum.TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL);
416 if (toscaElement.isRight()) {
417 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE);
418 Response errorResponse = buildErrorResponse(responseFormat);
419 EnumMap<AuditingFieldsKeysEnum, Object> additionalParam = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
420 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, uploadResourceInfo.getName());
421 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, additionalParam);
422 responseWrapper.setInnerElement(errorResponse);
427 protected void validateToscaTemplatePayloadName(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
428 String toscaTemplatePayloadName = uploadResourceInfo.getPayloadName();
429 boolean isValidSuffix = false;
430 if (toscaTemplatePayloadName != null && !toscaTemplatePayloadName.isEmpty()) {
431 for (String validSuffix : ImportUtils.Constants.TOSCA_YML_CSAR_VALID_SUFFIX) {
432 isValidSuffix = isValidSuffix || toscaTemplatePayloadName.toLowerCase().endsWith(validSuffix);
435 if (!isValidSuffix) {
436 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_FILE_EXTENSION);
437 Response errorResponse = buildErrorResponse(responseFormat);
438 EnumMap<AuditingFieldsKeysEnum, Object> additionalParam = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
439 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, uploadResourceInfo.getName());
440 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, additionalParam);
441 responseWrapper.setInnerElement(errorResponse);
446 protected void validateMD5(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfo, HttpServletRequest request, String resourceInfoJsonString) {
448 String recievedMD5 = request.getHeader(Constants.MD5_HEADER);
449 if (recievedMD5 == null) {
452 String calculateMD5 = GeneralUtility.calculateMD5ByString(resourceInfoJsonString);
453 isValid = calculateMD5.equals(recievedMD5);
456 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_CHECKSUM);
457 Response errorResponse = buildErrorResponse(responseFormat);
458 EnumMap<AuditingFieldsKeysEnum, Object> additionalParam = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
459 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceInfo.getName());
460 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, additionalParam);
461 responseWrapper.setInnerElement(errorResponse);
465 protected void validateComponentType(Wrapper<Response> responseWrapper, Wrapper<ComponentTypeEnum> componentWrapper, String componentType) {
467 if (componentType == null) {
470 if (ComponentTypeEnum.RESOURCE_PARAM_NAME.equalsIgnoreCase(componentType)) {
472 componentWrapper.setInnerElement(ComponentTypeEnum.RESOURCE);
473 } else if (ComponentTypeEnum.SERVICE_PARAM_NAME.equalsIgnoreCase(componentType)) {
475 componentWrapper.setInnerElement(ComponentTypeEnum.SERVICE);
481 log.debug("Invalid componentType:{}", componentType);
482 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
483 Response errorResp = buildErrorResponse(responseFormat);
484 responseWrapper.setInnerElement(errorResp);
488 protected void fillToscaTemplateFromJson(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo resourceInfo) {
489 if (resourceInfo.getPayloadData() == null || resourceInfo.getPayloadData().isEmpty()) {
490 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_PAYLOAD);
491 Response errorResponse = buildErrorResponse(responseFormat);
492 EnumMap<AuditingFieldsKeysEnum, Object> additionalParam = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
493 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resourceInfo.getName());
494 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, additionalParam);
495 responseWrapper.setInnerElement(errorResponse);
497 String toscaPayload = resourceInfo.getPayloadData();
498 String decodedPayload = (GeneralUtility.isBase64Encoded(toscaPayload)) ? new String(Base64.decodeBase64(toscaPayload)) : toscaPayload;
499 yamlStringWrapper.setInnerElement(decodedPayload);
504 protected void fillPayload(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, String resourceInfoJsonString, ResourceAuthorityTypeEnum resourceAuthorityEnum,
505 File file) throws FileNotFoundException {
507 if (responseWrapper.isEmpty()) {
508 if (resourceAuthorityEnum.isBackEndImport()) {
509 // PrePayload Validations
510 if (responseWrapper.isEmpty()) {
511 validateDataNotNull(responseWrapper, file, resourceInfoJsonString);
513 if (responseWrapper.isEmpty()) {
514 validateZip(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
517 // Fill PayLoad From File
518 if (responseWrapper.isEmpty()) {
519 fillToscaTemplateFromZip(yamlStringWrapper, uploadResourceInfoWrapper.getInnerElement().getPayloadName(), file);
523 // Fill PayLoad From JSON
524 if (responseWrapper.isEmpty()) {
525 fillToscaTemplateFromJson(responseWrapper, yamlStringWrapper, user, uploadResourceInfoWrapper.getInnerElement());
533 protected void specificResourceAuthorityValidations(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, HttpServletRequest request, String resourceInfoJsonString,
534 ResourceAuthorityTypeEnum resourceAuthorityEnum) throws FileNotFoundException {
536 if (responseWrapper.isEmpty()) {
537 // UI Only Validation
538 if (!resourceAuthorityEnum.isBackEndImport()) {
539 importUIValidations(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, request, resourceInfoJsonString);
542 // User Defined Type Resources
543 if (resourceAuthorityEnum.isUserTypeResource() && !CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {
544 if (responseWrapper.isEmpty()) {
545 validatePayloadNameSpace(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, yamlStringWrapper.getInnerElement());
552 protected void commonGeneralValidations(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, ResourceAuthorityTypeEnum resourceAuthorityEnum, String userId,
553 String resourceInfoJsonString) {
555 if (responseWrapper.isEmpty()) {
556 validateUserExist(responseWrapper, userWrapper, userId);
559 if (responseWrapper.isEmpty()) {
560 validateUserRole(responseWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum);
563 if (responseWrapper.isEmpty()) {
564 validateAndFillResourceJson(responseWrapper, uploadResourceInfoWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum, resourceInfoJsonString);
567 if (responseWrapper.isEmpty()) {
568 validateToscaTemplatePayloadName(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
570 if (responseWrapper.isEmpty()) {
571 validateResourceType(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
576 private void validateResourceType(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
577 String resourceType = uploadResourceInfo.getResourceType();
578 if (resourceType == null || !ResourceTypeEnum.contains(resourceType)) {
579 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
580 Response errorResponse = buildErrorResponse(responseFormat);
581 EnumMap<AuditingFieldsKeysEnum, Object> additionalParam = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
582 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, uploadResourceInfo.getName());
583 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, additionalParam);
584 responseWrapper.setInnerElement(errorResponse);
588 protected void importUIValidations(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, HttpServletRequest request, String resourceInfoJsonString) {
589 if (responseWrapper.isEmpty()) {
590 validateMD5(responseWrapper, user, resourceInfo, request, resourceInfoJsonString);
592 if (responseWrapper.isEmpty() && request != null && request.getMethod() != null && request.getMethod().equals("POST")) {
593 validateResourceDoesNotExist(responseWrapper, user, resourceInfo.getName());
597 protected void commonPayloadValidations(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo uploadResourceInfo) {
599 if (responseWrapper.isEmpty()) {
600 validatePayloadIsYml(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
602 if (responseWrapper.isEmpty()) {
603 validatePayloadIsTosca(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
605 if (responseWrapper.isEmpty()) {
606 validatePayloadIsNotService(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
608 if (responseWrapper.isEmpty()) {
609 validatePayloadIsSingleResource(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
613 protected void topologyTemplatePayloadValidations(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo uploadResourceInfo) {
615 if (responseWrapper.isEmpty()) {
616 validatePayloadIsYml(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
618 if (responseWrapper.isEmpty()) {
619 validatePayloadIsTosca(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
621 if (responseWrapper.isEmpty()) {
622 validatePayloadIsTopologyTemplate(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
627 protected void handleImport(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfoObject, String yamlAsString, ResourceAuthorityTypeEnum authority, boolean createNewVersion, String resourceUniqueId) {
628 Either<ImmutablePair<org.openecomp.sdc.be.model.Resource, ActionStatus>, ResponseFormat> createOrUpdateResponse = null;
629 Response response = null;
630 Object representation = null;
632 if (CsarValidationUtils.isCsarPayloadName(resourceInfoObject.getPayloadName())) {
633 log.debug("import resource from csar");
634 createOrUpdateResponse = importResourceFromUICsar(resourceInfoObject, user, resourceUniqueId);
635 } else if (!authority.isUserTypeResource()) {
636 log.debug("import normative type resource");
637 createOrUpdateResponse = resourceImportManager.importNormativeResource(yamlAsString, resourceInfoObject, user, createNewVersion, true);
639 log.debug("import user resource (not normative type)");
640 createOrUpdateResponse = resourceImportManager.importUserDefinedResource(yamlAsString, resourceInfoObject, user, false, false);
642 if (createOrUpdateResponse.isRight()) {
643 response = buildErrorResponse(createOrUpdateResponse.right().value());
646 representation = RepresentationUtils.toRepresentation(createOrUpdateResponse.left().value().getLeft());
647 } catch (IOException e) {
650 ActionStatus successStatus = createOrUpdateResponse.left().value().right;
651 response = buildOkResponse(getComponentsUtils().getResponseFormat(successStatus), representation);
653 responseWrapper.setInnerElement(response);
656 private Either<ImmutablePair<org.openecomp.sdc.be.model.Resource, ActionStatus>, ResponseFormat> importResourceFromUICsar(UploadResourceInfo resourceInfoObject, User user, String resourceUniqueId) {
658 Either<org.openecomp.sdc.be.model.Resource, ResponseFormat> createOrUpdateResourceRes = null;
659 ImmutablePair<org.openecomp.sdc.be.model.Resource, ActionStatus> result = null;
660 ActionStatus actionStatus = null;
661 org.openecomp.sdc.be.model.Resource resource = new org.openecomp.sdc.be.model.Resource();
662 String payloadName = resourceInfoObject.getPayloadName();
663 fillResourceFromResourceInfoObject(resource, resourceInfoObject);
665 Either<Map<String, byte[]>, ResponseFormat> csarUIPayloadRes = getScarFromPayload(resourceInfoObject);
666 if (csarUIPayloadRes.isRight()) {
667 return Either.right(csarUIPayloadRes.right().value());
669 Map<String, byte[]> csarUIPayload = csarUIPayloadRes.left().value();
671 createOrUpdateResourceRes = getAndValidateCsarYaml(csarUIPayload, resource, user, payloadName);
672 if (createOrUpdateResourceRes.isRight()) {
673 return Either.right(createOrUpdateResourceRes.right().value());
675 if (resourceUniqueId == null || resourceUniqueId.isEmpty()) {
676 createOrUpdateResourceRes = resourceImportManager.getResourceBusinessLogic().createResource(resource, user, csarUIPayload, payloadName);
677 if (createOrUpdateResourceRes.isRight()) {
678 return Either.right(createOrUpdateResourceRes.right().value());
680 actionStatus = ActionStatus.CREATED;
682 createOrUpdateResourceRes = resourceImportManager.getResourceBusinessLogic().validateAndUpdateResourceFromCsar(resource, user, csarUIPayload, payloadName, resourceUniqueId);
683 if (createOrUpdateResourceRes.isRight()) {
684 return Either.right(createOrUpdateResourceRes.right().value());
686 actionStatus = ActionStatus.OK;
688 result = new ImmutablePair<org.openecomp.sdc.be.model.Resource, ActionStatus>(createOrUpdateResourceRes.left().value(), actionStatus);
689 return Either.left(result);
692 private Either<org.openecomp.sdc.be.model.Resource, ResponseFormat> getAndValidateCsarYaml(Map<String, byte[]> csarUIPayload, org.openecomp.sdc.be.model.Resource resource, User user, String csarUUID) {
694 Either<ImmutablePair<String, String>, ResponseFormat> getToscaYamlRes = CsarValidationUtils.getToscaYaml(csarUIPayload, csarUUID, getComponentsUtils());
696 if (getToscaYamlRes.isRight()) {
697 ResponseFormat responseFormat = getToscaYamlRes.right().value();
698 log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat);
699 BeEcompErrorManager.getInstance().logBeDaoSystemError("Creating resource from CSAR: fetching CSAR with id " + csarUUID + " failed");
700 getComponentsUtils().auditResource(responseFormat, user, resource, "", "", AuditingActionEnum.CREATE_RESOURCE, null);
701 return Either.right(responseFormat);
703 String toscaYaml = getToscaYamlRes.left().value().getValue();
705 log.debug("checking tosca template is valid yml");
706 YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
707 boolean isValid = yamlConvertor.isValidYaml(toscaYaml.getBytes());
709 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
710 EnumMap<AuditingFieldsKeysEnum, Object> additionalParam = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
711 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resource.getName());
712 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, additionalParam);
713 return Either.right(responseFormat);
716 log.debug("checking payload is valid tosca");
717 String heatDecodedPayload = (GeneralUtility.isBase64Encoded(toscaYaml)) ? new String(Base64.decodeBase64(toscaYaml)) : toscaYaml;
718 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(heatDecodedPayload);
719 Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, ToscaTagNamesEnum.TOSCA_VERSION);
721 if (findFirstToscaStringElement.isRight()) {
724 String defenitionVersionFound = findFirstToscaStringElement.left().value();
725 if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
728 isValid = ImportUtils.Constants.TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
733 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
734 EnumMap<AuditingFieldsKeysEnum, Object> additionalParam = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
735 additionalParam.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, resource.getName());
736 getComponentsUtils().auditResource(responseFormat, user, null, "", "", AuditingActionEnum.IMPORT_RESOURCE, additionalParam);
737 return Either.right(responseFormat);
739 return Either.left(resource);
742 private void fillResourceFromResourceInfoObject(org.openecomp.sdc.be.model.Resource resource, UploadResourceInfo resourceInfoObject) {
743 if (resource != null && resourceInfoObject != null) {
744 resource.setDescription(resourceInfoObject.getDescription());
745 resource.setTags(resourceInfoObject.getTags());
746 resource.setCategories(resourceInfoObject.getCategories());
747 resource.setContactId(resourceInfoObject.getContactId());
748 resource.setName(resourceInfoObject.getName());
749 resource.setIcon(resourceInfoObject.getResourceIconPath());
750 resource.setVendorName(resourceInfoObject.getVendorName());
751 resource.setVendorRelease(resourceInfoObject.getVendorRelease());
752 resource.setResourceType(ResourceTypeEnum.valueOf(resourceInfoObject.getResourceType()));
753 List<UploadArtifactInfo> artifactList = resourceInfoObject.getArtifactList();
754 if (artifactList != null) {
755 Map<String, ArtifactDefinition> artifactsHM = new HashMap<String, ArtifactDefinition>();
756 for (UploadArtifactInfo artifact : artifactList) {
757 ArtifactDefinition artifactDef = new ArtifactDefinition();
758 artifactDef.setArtifactName(artifact.getArtifactName());
759 artifactDef.setArtifactType(artifact.getArtifactType().getType());
760 artifactDef.setDescription(artifact.getArtifactDescription());
761 artifactDef.setPayloadData(artifact.getArtifactData());
762 artifactDef.setArtifactRef(artifact.getArtifactPath());
763 artifactsHM.put(artifactDef.getArtifactName(), artifactDef);
765 resource.setArtifacts(artifactsHM);
771 private Either<Map<String, byte[]>, ResponseFormat> getScarFromPayload(UploadResourceInfo innerElement) {
772 String csarUUID = innerElement.getPayloadName();
773 String payloadData = innerElement.getPayloadData();
774 if (payloadData == null) {
775 log.info("Failed to decode received csar", csarUUID);
776 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_NOT_FOUND, csarUUID));
779 byte[] decodedPayload = (GeneralUtility.isBase64Encoded(payloadData)) ? Base64.decodeBase64(payloadData.getBytes(StandardCharsets.UTF_8)) : payloadData.getBytes(StandardCharsets.UTF_8);
780 if (decodedPayload == null) {
781 log.info("Failed to decode received csar", csarUUID);
782 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_NOT_FOUND, csarUUID));
785 Map<String, byte[]> csar = ZipUtil.readZip(decodedPayload);
787 log.info("Failed to unzip received csar", csarUUID);
788 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID, csarUUID));
790 return Either.left(csar);
793 protected void validateInputStream(final HttpServletRequest request, Wrapper<String> dataWrapper, Wrapper<ResponseFormat> errorWrapper) throws IOException {
794 InputStream inputStream = request.getInputStream();
795 byte[] bytes = IOUtils.toByteArray(inputStream);
796 if (bytes == null || bytes.length == 0) {
797 log.info("Empty body was sent.");
798 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
800 dataWrapper.setInnerElement(new String(bytes, StandardCharsets.UTF_8));
805 protected <T> void validateClassParse(String data, Wrapper<T> parsedClassWrapper, Supplier<Class<T>> classGen, Wrapper<ResponseFormat> errorWrapper) {
807 T parsedClass = gson.fromJson(data, classGen.get());
808 if (parsedClass == null) {
809 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
811 parsedClassWrapper.setInnerElement(parsedClass);
813 } catch (JsonSyntaxException e) {
814 log.debug("Failed to decode received {} {} to object.", classGen.get().getName(), data, e);
815 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
819 protected void validateComponentInstanceBusinessLogic(HttpServletRequest request, String containerComponentType, Wrapper<ComponentInstanceBusinessLogic> blWrapper, Wrapper<ResponseFormat> errorWrapper) {
820 ServletContext context = request.getSession().getServletContext();
822 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
823 ComponentInstanceBusinessLogic componentInstanceLogic = getComponentInstanceBL(context, componentTypeEnum);
824 if (componentInstanceLogic == null) {
825 log.debug("Unsupported component type {}", containerComponentType);
826 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
828 blWrapper.setInnerElement(componentInstanceLogic);
832 protected <T> Response buildResponseFromElement(Wrapper<ResponseFormat> errorWrapper, Wrapper<T> attributeWrapper) throws IOException {
834 if (errorWrapper.isEmpty()) {
835 ObjectMapper mapper = new ObjectMapper();
836 String result = mapper.writeValueAsString(attributeWrapper.getInnerElement());
837 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
839 response = buildErrorResponse(errorWrapper.getInnerElement());