2  * ============LICENSE_START=======================================================
 
   3  *  Copyright (C) 2019 Nordix Foundation
 
   4  *  ================================================================================
 
   5  *  Licensed under the Apache License, Version 2.0 (the "License");
 
   6  *  you may not use this file except in compliance with the License.
 
   7  *  You may obtain a copy of the License at
 
   9  *        http://www.apache.org/licenses/LICENSE-2.0
 
  10  *  Unless required by applicable law or agreed to in writing, software
 
  11  *  distributed under the License is distributed on an "AS IS" BASIS,
 
  12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  13  *  See the License for the specific language governing permissions and
 
  14  *  limitations under the License.
 
  16  *  SPDX-License-Identifier: Apache-2.0
 
  17  *  ============LICENSE_END=========================================================
 
  20 package org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding;
 
  22 import static org.openecomp.sdc.common.errors.Messages.PACKAGE_EMPTY_ERROR;
 
  23 import static org.openecomp.sdc.common.errors.Messages.PACKAGE_INVALID_ERROR;
 
  24 import static org.openecomp.sdc.common.errors.Messages.PACKAGE_INVALID_EXTENSION;
 
  25 import static org.openecomp.sdc.common.errors.Messages.PACKAGE_MISSING_INTERNAL_PACKAGE;
 
  26 import static org.openecomp.sdc.common.errors.Messages.PACKAGE_PROCESS_ERROR;
 
  27 import static org.openecomp.sdc.common.errors.Messages.PACKAGE_PROCESS_INTERNAL_PACKAGE_ERROR;
 
  28 import static org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManager.ALLOWED_CERTIFICATE_EXTENSIONS;
 
  29 import static org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManager.ALLOWED_SIGNATURE_EXTENSIONS;
 
  31 import java.io.ByteArrayInputStream;
 
  33 import java.io.FileInputStream;
 
  34 import java.io.InputStream;
 
  35 import java.nio.ByteBuffer;
 
  36 import java.nio.charset.StandardCharsets;
 
  37 import java.util.ArrayList;
 
  38 import java.util.HashSet;
 
  39 import java.util.List;
 
  41 import java.util.Objects;
 
  42 import java.util.Optional;
 
  44 import org.apache.commons.collections4.CollectionUtils;
 
  45 import org.apache.commons.collections4.MapUtils;
 
  46 import org.apache.commons.io.FilenameUtils;
 
  47 import org.openecomp.core.utilities.file.FileContentHandler;
 
  48 import org.openecomp.core.utilities.json.JsonUtil;
 
  49 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
 
  50 import org.openecomp.sdc.common.utils.SdcCommon;
 
  51 import org.openecomp.sdc.common.zip.exception.ZipException;
 
  52 import org.openecomp.sdc.common.utils.CommonUtil;
 
  53 import org.openecomp.sdc.datatypes.error.ErrorLevel;
 
  54 import org.openecomp.sdc.datatypes.error.ErrorMessage;
 
  55 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
 
  56 import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
 
  57 import org.openecomp.sdc.logging.api.Logger;
 
  58 import org.openecomp.sdc.logging.api.LoggerFactory;
 
  59 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackage;
 
  60 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo;
 
  61 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardSignedPackage;
 
  63 public class OnboardingPackageProcessor {
 
  64     private static final Logger LOGGER = LoggerFactory.getLogger(OnboardingPackageProcessor.class);
 
  65     private static final String CSAR_EXTENSION = "csar";
 
  66     private static final String ZIP_EXTENSION = "zip";
 
  67     private static  boolean helmBase = false;
 
  69     private final String packageFileName;
 
  70     private final byte[] packageFileContent;
 
  71     private FileContentHandler onboardPackageContentHandler;
 
  72     private Set<ErrorMessage> errorMessageSet = new HashSet<>();
 
  73     private OnboardPackageInfo onboardPackageInfo;
 
  75     public OnboardingPackageProcessor(final String packageFileName, final byte[] packageFileContent) {
 
  76         this.packageFileName = packageFileName;
 
  77         this.packageFileContent = packageFileContent;
 
  78         onboardPackageInfo = processPackage();
 
  81     private OnboardPackageInfo processPackage() {
 
  82         if (!hasValidExtension()) {
 
  83             final String message = PACKAGE_INVALID_EXTENSION.formatMessage(packageFileName, String.join(", ", CSAR_EXTENSION, ZIP_EXTENSION));
 
  84             reportError(ErrorLevel.ERROR, message);
 
  88             onboardPackageContentHandler = CommonUtil.getZipContent(packageFileContent);
 
  89         } catch (final ZipException e) {
 
  90             final String message = PACKAGE_PROCESS_ERROR.formatMessage(packageFileName);
 
  91             LOGGER.error(message, e);
 
  92             reportError(ErrorLevel.ERROR, message);
 
  95         if (isPackageEmpty()) {
 
  96             final String message = PACKAGE_EMPTY_ERROR.formatMessage(packageFileName);
 
  97             reportError(ErrorLevel.ERROR, message);
 
 101         final String packageName = FilenameUtils.getBaseName(packageFileName);
 
 102         final String packageExtension = FilenameUtils.getExtension(packageFileName);
 
 104         if (hasSignedPackageStructure()) {
 
 105             return processSignedPackage(packageName, packageExtension);
 
 107             if (packageExtension.equalsIgnoreCase(CSAR_EXTENSION)) {
 
 108                 final OnboardPackage onboardPackage = new OnboardPackage(packageName, packageExtension,
 
 109                     ByteBuffer.wrap(packageFileContent), new OnboardingPackageContentHandler(onboardPackageContentHandler));
 
 110                 return new OnboardPackageInfo(onboardPackage, OnboardingTypesEnum.CSAR);
 
 111             } else if (packageExtension.equalsIgnoreCase(ZIP_EXTENSION)) {
 
 113                 final OnboardPackage onboardPackage = new OnboardPackage(packageName, packageExtension,
 
 114                     ByteBuffer.wrap(packageFileContent), onboardPackageContentHandler);
 
 115                 return new OnboardPackageInfo(onboardPackage, OnboardingTypesEnum.ZIP);
 
 119         reportError(ErrorLevel.ERROR, PACKAGE_INVALID_ERROR.formatMessage(packageFileName));
 
 123     private void addDummyHeat() {
 
 124         // temporary fix for adding dummy base
 
 125         List<FileData> newfiledata = new ArrayList<>();
 
 126         try (InputStream zipFileManifest = onboardPackageContentHandler.getFileContentAsStream(SdcCommon.MANIFEST_NAME)) {
 
 127             ManifestContent manifestContent =
 
 128                     JsonUtil.json2Object(zipFileManifest, ManifestContent.class);
 
 129             for (FileData fileData : manifestContent.getData()) {
 
 130                 if (Objects.nonNull(fileData.getType()) &&
 
 131                         fileData.getType().equals(FileData.Type.HELM) && fileData.getBase()) {
 
 133                     fileData.setBase(false);
 
 134                     FileData dummyHeat = new FileData();
 
 135                     dummyHeat.setBase(true);
 
 136                     dummyHeat.setFile("base_template_dummy_ignore.yaml");
 
 137                     dummyHeat.setType(FileData.Type.HEAT);
 
 138                     FileData dummyEnv = new FileData();
 
 139                     dummyEnv.setBase(false);
 
 140                     dummyEnv.setFile("base_template_dummy_ignore.env");
 
 141                     dummyEnv.setType(FileData.Type.HEAT_ENV);
 
 142                     List<FileData> dataEnvList = new ArrayList<>();
 
 143                     dataEnvList.add(dummyEnv);
 
 144                     dummyHeat.setData(dataEnvList);
 
 145                     newfiledata.add(dummyHeat);
 
 146                     String filePath = new File("").getAbsolutePath() + "/resources";
 
 147                     File envFilePath = new File(filePath + "/base_template.env");
 
 148                     File baseFilePath = new File(filePath + "/base_template.yaml");
 
 150                             InputStream envStream = new FileInputStream(envFilePath);
 
 151                             InputStream baseStream = new FileInputStream(baseFilePath);) {
 
 152                         onboardPackageContentHandler.addFile("base_template_dummy_ignore.env", envStream);
 
 153                         onboardPackageContentHandler.addFile("base_template_dummy_ignore.yaml", baseStream);
 
 154                     } catch (Exception e) {
 
 155                         LOGGER.error("Failed creating input stream {}", e);
 
 160                 manifestContent.getData().addAll(newfiledata);
 
 161                 InputStream manifestContentStream = new ByteArrayInputStream((JsonUtil.object2Json(manifestContent)).getBytes(StandardCharsets.UTF_8));
 
 162                 onboardPackageContentHandler.remove(SdcCommon.MANIFEST_NAME);
 
 163                 onboardPackageContentHandler.addFile(SdcCommon.MANIFEST_NAME, manifestContentStream);
 
 165         } catch (Exception e) {
 
 166             final String message = PACKAGE_INVALID_ERROR.formatMessage(packageFileName);
 
 167             LOGGER.error(message, e);
 
 170     private boolean hasValidExtension() {
 
 171         final String packageExtension = FilenameUtils.getExtension(packageFileName);
 
 172         return packageExtension.equalsIgnoreCase(CSAR_EXTENSION) || packageExtension.equalsIgnoreCase(ZIP_EXTENSION);
 
 175     private OnboardPackageInfo processSignedPackage(final String packageName, final String packageExtension) {
 
 176         final String internalPackagePath = findInternalPackagePath().orElse(null);
 
 177         if (internalPackagePath == null) {
 
 178             reportError(ErrorLevel.ERROR, PACKAGE_MISSING_INTERNAL_PACKAGE.getErrorMessage());
 
 181         final String signatureFilePath = findSignatureFilePath().orElse(null);
 
 182         final String certificateFilePath = findCertificateFilePath().orElse(null);
 
 183         final OnboardSignedPackage onboardSignedPackage =
 
 184             new OnboardSignedPackage(packageName, packageExtension, ByteBuffer.wrap(packageFileContent),
 
 185                 onboardPackageContentHandler, signatureFilePath, internalPackagePath, certificateFilePath);
 
 187         final String internalPackageName = FilenameUtils.getName(internalPackagePath);
 
 188         final String internalPackageBaseName = FilenameUtils.getBaseName(internalPackagePath);
 
 189         final String internalPackageExtension = FilenameUtils.getExtension(internalPackagePath);
 
 190         final byte[] internalPackageContent = onboardPackageContentHandler.getFileContent(internalPackagePath);
 
 191         final OnboardPackage onboardPackage;
 
 193             final OnboardingPackageContentHandler fileContentHandler =
 
 194                 new OnboardingPackageContentHandler(CommonUtil.getZipContent(internalPackageContent));
 
 195             onboardPackage = new OnboardPackage(internalPackageBaseName, internalPackageExtension,
 
 196                 internalPackageContent, fileContentHandler);
 
 197         } catch (final ZipException e) {
 
 198             final String message = PACKAGE_PROCESS_INTERNAL_PACKAGE_ERROR.formatMessage(internalPackageName);
 
 199             LOGGER.error(message, e);
 
 200             reportError(ErrorLevel.ERROR, message);
 
 204         return new OnboardPackageInfo(onboardSignedPackage, onboardPackage, OnboardingTypesEnum.SIGNED_CSAR);
 
 207     private void reportError(final ErrorLevel errorLevel, final String message) {
 
 208         errorMessageSet.add(new ErrorMessage(errorLevel, message));
 
 211     public boolean hasErrors() {
 
 212         return !errorMessageSet.isEmpty();
 
 215     public Set<ErrorMessage> getErrorMessageSet() {
 
 216         return errorMessageSet;
 
 219     private Optional<String> findInternalPackagePath() {
 
 220         return onboardPackageContentHandler.getFileList().stream()
 
 221             .filter(filePath -> {
 
 222                     final String extension = FilenameUtils.getExtension(filePath);
 
 223                     return CSAR_EXTENSION.equalsIgnoreCase(extension) || ZIP_EXTENSION.equalsIgnoreCase(extension);
 
 229     private boolean isPackageEmpty() {
 
 230         return MapUtils.isEmpty(onboardPackageContentHandler.getFiles());
 
 233     private boolean hasSignedPackageStructure() {
 
 234         if (MapUtils.isEmpty(onboardPackageContentHandler.getFiles()) || !CollectionUtils.isEmpty(
 
 235             onboardPackageContentHandler.getFolderList())) {
 
 238         final int numberOfFiles = onboardPackageContentHandler.getFileList().size();
 
 239         if (numberOfFiles == 2) {
 
 240             return hasOneInternalPackageFile(onboardPackageContentHandler) &&
 
 241                 hasOneSignatureFile(onboardPackageContentHandler);
 
 244         if (numberOfFiles == 3) {
 
 245             return hasOneInternalPackageFile(onboardPackageContentHandler) &&
 
 246                 hasOneSignatureFile(onboardPackageContentHandler) &&
 
 247                 hasOneCertificateFile(onboardPackageContentHandler);
 
 253     private boolean hasOneInternalPackageFile(final FileContentHandler fileContentHandler) {
 
 254         return fileContentHandler.getFileList().parallelStream()
 
 255             .map(FilenameUtils::getExtension)
 
 256             .map(String::toLowerCase)
 
 257             .filter(file -> file.endsWith(CSAR_EXTENSION)).count() == 1;
 
 260     private boolean hasOneSignatureFile(final FileContentHandler fileContentHandler) {
 
 261         return fileContentHandler.getFileList().parallelStream()
 
 262             .map(FilenameUtils::getExtension)
 
 263             .map(String::toLowerCase)
 
 264             .filter(ALLOWED_SIGNATURE_EXTENSIONS::contains).count() == 1;
 
 267     private boolean hasOneCertificateFile(final FileContentHandler fileContentHandler) {
 
 268         return fileContentHandler.getFileList().parallelStream()
 
 269             .map(FilenameUtils::getExtension)
 
 270             .map(String::toLowerCase)
 
 271             .filter(ALLOWED_CERTIFICATE_EXTENSIONS::contains).count() == 1;
 
 274     private Optional<String> findSignatureFilePath() {
 
 275         final Map<String, byte[]> files = onboardPackageContentHandler.getFiles();
 
 276         return files.keySet().stream()
 
 277             .filter(fileName -> ALLOWED_SIGNATURE_EXTENSIONS.contains(FilenameUtils.getExtension(fileName).toLowerCase()))
 
 281     private Optional<String> findCertificateFilePath() {
 
 282         final Map<String, byte[]> files = onboardPackageContentHandler.getFiles();
 
 283         return files.keySet().stream()
 
 284             .filter(fileName -> ALLOWED_CERTIFICATE_EXTENSIONS.contains(FilenameUtils.getExtension(fileName).toLowerCase()))
 
 288     public Optional<OnboardPackageInfo> getOnboardPackageInfo() {
 
 289         return Optional.ofNullable(onboardPackageInfo);