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();
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);