aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/reception-plugins/src/main/java/org/onap/policy/distribution
diff options
context:
space:
mode:
authoradheli.tavares <adheli.tavares@est.tech>2022-05-12 13:58:48 +0100
committeradheli.tavares <adheli.tavares@est.tech>2022-05-12 15:25:14 +0100
commit2a58e25bee3bf029e1696a443f23495e119c5855 (patch)
treecdb4ff9f1113251f0ea3a5ad7c667cfd0452c665 /plugins/reception-plugins/src/main/java/org/onap/policy/distribution
parent1537b4665f9050bb2efe6f4f0aba2fb38d52a0ef (diff)
Security issues from sonar cloud fixes
Issue-ID: POLICY-4168 Change-Id: Iedac6c95be452be81e8c73055193b4707735ef56 Signed-off-by: adheli.tavares <adheli.tavares@est.tech>
Diffstat (limited to 'plugins/reception-plugins/src/main/java/org/onap/policy/distribution')
-rw-r--r--plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/decoding/policy/file/AutomationCompositionDecoderFileInCsar.java63
-rw-r--r--plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/decoding/policy/file/PolicyDecoderFileInCsarToPolicy.java25
-rw-r--r--plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/handling/sdc/SdcReceptionHandler.java88
-rw-r--r--plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/util/ReceptionUtil.java103
4 files changed, 160 insertions, 119 deletions
diff --git a/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/decoding/policy/file/AutomationCompositionDecoderFileInCsar.java b/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/decoding/policy/file/AutomationCompositionDecoderFileInCsar.java
index fb7a8d99..7087d7ca 100644
--- a/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/decoding/policy/file/AutomationCompositionDecoderFileInCsar.java
+++ b/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/decoding/policy/file/AutomationCompositionDecoderFileInCsar.java
@@ -20,14 +20,10 @@
package org.onap.policy.distribution.reception.decoding.policy.file;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
+import java.util.HashMap;
+import java.util.Map;
import org.onap.policy.common.parameters.ParameterService;
import org.onap.policy.common.utils.coder.CoderException;
import org.onap.policy.distribution.model.Csar;
@@ -72,53 +68,28 @@ public class AutomationCompositionDecoderFileInCsar implements PolicyDecoder<Csa
public Collection<ToscaEntity> decode(final Csar csar) throws PolicyDecodingException {
final Collection<ToscaEntity> automationCompositionList = new ArrayList<>();
- try (var zipFile = new ZipFile(csar.getCsarFilePath())) {
- final List<? extends ZipEntry> entries = zipFile.stream()
- .filter(entry -> entry.getName().contains(decoderParameters.getAutomationCompositionType()))
- .collect(Collectors.toList());
-
- for (ZipEntry entry : entries) {
- ReceptionUtil.validateZipEntry(entry.getName(), csar.getCsarFilePath(), entry.getSize());
- final ToscaServiceTemplate automationComposition = ReceptionUtil.decodeFile(zipFile, entry);
+ try {
+ Map<String, ToscaServiceTemplate> templates = new HashMap<>();
+ ReceptionUtil.unzip(csar.getCsarFilePath(), templates,
+ decoderParameters.getAutomationCompositionType(), NODE_TYPES, DATA_TYPES);
- if (null != automationComposition.getToscaTopologyTemplate()) {
- validateTypes(zipFile, NODE_TYPES)
- .ifPresent(node -> automationComposition.setNodeTypes(node.getNodeTypes()));
+ var node = templates.get(NODE_TYPES);
+ var data = templates.get(DATA_TYPES);
- validateTypes(zipFile, DATA_TYPES)
- .ifPresent(data -> automationComposition.setDataTypes(data.getDataTypes()));
+ templates.forEach((entry, t) -> {
+ if (entry.contains(decoderParameters.getAutomationCompositionType())
+ && t.getToscaTopologyTemplate() != null) {
+ t.setNodeTypes(node != null ? node.getNodeTypes() : null);
+ t.setDataTypes(data != null ? data.getDataTypes() : null);
- automationCompositionList.add(automationComposition);
+ automationCompositionList.add(t);
}
- }
- } catch (final IOException | CoderException exp) {
+ });
+
+ } catch (final CoderException exp) {
throw new PolicyDecodingException("Failed decoding the acm", exp);
}
return automationCompositionList;
}
-
- /**
- * Decode and validate if node or data type is available withing ACM csar file.
- *
- * @param zipFile full csar file
- * @return tosca template with parsed node/data type
- * @throws CoderException if file can't be parsed
- */
- private Optional<ToscaServiceTemplate> validateTypes(final ZipFile zipFile, String type)
- throws CoderException {
-
- try {
- ToscaServiceTemplate template = null;
- final Optional<? extends ZipEntry> file = zipFile.stream()
- .filter(entry -> entry.getName().contains(type)).findFirst();
-
- if (file.isPresent()) {
- template = ReceptionUtil.decodeFile(zipFile, file.get());
- }
- return Optional.ofNullable(template);
- } catch (final IOException | CoderException exp) {
- throw new CoderException("Couldn't decode " + type + " type", exp);
- }
- }
}
diff --git a/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/decoding/policy/file/PolicyDecoderFileInCsarToPolicy.java b/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/decoding/policy/file/PolicyDecoderFileInCsarToPolicy.java
index 8d0a554a..86f857a8 100644
--- a/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/decoding/policy/file/PolicyDecoderFileInCsarToPolicy.java
+++ b/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/decoding/policy/file/PolicyDecoderFileInCsarToPolicy.java
@@ -23,13 +23,10 @@
package org.onap.policy.distribution.reception.decoding.policy.file;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
+import java.util.HashMap;
+import java.util.Map;
import org.onap.policy.common.parameters.ParameterService;
import org.onap.policy.common.utils.coder.CoderException;
import org.onap.policy.distribution.model.Csar;
@@ -70,19 +67,15 @@ public class PolicyDecoderFileInCsarToPolicy implements PolicyDecoder<Csar, Tosc
*/
@Override
public Collection<ToscaEntity> decode(final Csar csar) throws PolicyDecodingException {
- final Collection<ToscaEntity> policyList = new ArrayList<>();
+ final Collection<ToscaEntity> policyList;
- try (var zipFile = new ZipFile(csar.getCsarFilePath())) {
- final List<? extends ZipEntry> entries = zipFile.stream()
- .filter(entry -> entry.getName().contains(decoderParameters.getPolicyTypeFileName())
- || entry.getName().contains(decoderParameters.getPolicyFileName())).collect(Collectors.toList());
+ try {
+ Map<String, ToscaServiceTemplate> templates = new HashMap<>();
+ ReceptionUtil.unzip(csar.getCsarFilePath(), templates, decoderParameters.getPolicyFileName(),
+ decoderParameters.getPolicyTypeFileName());
+ policyList = new ArrayList<>(templates.values());
- for (ZipEntry entry : entries) {
- ReceptionUtil.validateZipEntry(entry.getName(), csar.getCsarFilePath(), entry.getSize());
- final ToscaServiceTemplate policy = ReceptionUtil.decodeFile(zipFile, entry);
- policyList.add(policy);
- }
- } catch (final IOException | CoderException exp) {
+ } catch (final CoderException exp) {
throw new PolicyDecodingException("Failed decoding the policy", exp);
}
diff --git a/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/handling/sdc/SdcReceptionHandler.java b/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/handling/sdc/SdcReceptionHandler.java
index 5fd76bea..ff915613 100644
--- a/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/handling/sdc/SdcReceptionHandler.java
+++ b/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/handling/sdc/SdcReceptionHandler.java
@@ -1,7 +1,7 @@
/*-
* ============LICENSE_START=======================================================
* Copyright (C) 2018 Ericsson. All rights reserved.
- * Copyright (C) 2019 Nordix Foundation.
+ * Copyright (C) 2019, 2022 Nordix Foundation.
* Modifications Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
* Modifications Copyright (C) 2021 Bell Canada. All rights reserved.
* ================================================================================
@@ -28,6 +28,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import org.onap.policy.common.parameters.ParameterService;
import org.onap.policy.distribution.model.Csar;
@@ -62,7 +63,7 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
private SdcReceptionHandlerStatus sdcReceptionHandlerStatus = SdcReceptionHandlerStatus.STOPPED;
private IDistributionClient distributionClient;
private SdcConfiguration sdcConfig;
- private AtomicInteger nbOfNotificationsOngoing = new AtomicInteger();
+ private final AtomicInteger nbOfNotificationsOngoing = new AtomicInteger();
private int retryDelay;
private SdcClientHandler sdcClientHandler;
@@ -73,7 +74,7 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
@Override
protected void initializeReception(final String parameterGroupName) {
final SdcReceptionHandlerConfigurationParameterGroup handlerParameters =
- ParameterService.get(parameterGroupName);
+ ParameterService.get(parameterGroupName);
retryDelay = handlerParameters.getRetryDelay() < 30 ? 30 : handlerParameters.getRetryDelay();
sdcConfig = new SdcConfiguration(handlerParameters);
distributionClient = createSdcDistributionClient();
@@ -101,7 +102,7 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
*
* @param newStatus the new status
*/
- private final synchronized void changeSdcReceptionHandlerStatus(final SdcReceptionHandlerStatus newStatus) {
+ private synchronized void changeSdcReceptionHandlerStatus(final SdcReceptionHandlerStatus newStatus) {
switch (newStatus) {
case INIT:
case STOPPED:
@@ -130,7 +131,6 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
/**
* Method to initialize the SDC client.
- *
*/
protected void initializeSdcClient() {
@@ -142,7 +142,7 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
final IDistributionClientResult clientResult = distributionClient.init(sdcConfig, this);
if (!clientResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
LOGGER.error("SDC client initialization failed with reason: {}. Initialization will be retried after {} {}",
- clientResult.getDistributionMessageResult(), retryDelay, SECONDS);
+ clientResult.getDistributionMessageResult(), retryDelay, SECONDS);
return;
}
LOGGER.debug("SDC Client is initialized successfully");
@@ -151,7 +151,6 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
/**
* Method to start the SDC client.
- *
*/
protected void startSdcClient() {
@@ -163,7 +162,7 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
final IDistributionClientResult clientResult = distributionClient.start();
if (!clientResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
LOGGER.error("SDC client start failed with reason: {}. Start will be retried after {} {}",
- clientResult.getDistributionMessageResult(), retryDelay, SECONDS);
+ clientResult.getDistributionMessageResult(), retryDelay, SECONDS);
return;
}
LOGGER.debug("SDC Client is started successfully");
@@ -173,14 +172,13 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
/**
* Method to stop the SDC client.
- *
*/
protected void stopSdcClient() {
LOGGER.debug("Going to stop the SDC Client...");
final IDistributionClientResult clientResult = distributionClient.stop();
if (!clientResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
LOGGER.error("SDC client stop failed with reason: {}. Stop will be retried after {} {}",
- clientResult.getDistributionMessageResult(), retryDelay, SECONDS);
+ clientResult.getDistributionMessageResult(), retryDelay, SECONDS);
return;
}
LOGGER.debug("SDC Client is stopped successfully");
@@ -199,29 +197,29 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
for (final IArtifactInfo artifact : notificationData.getServiceArtifacts()) {
try {
final IDistributionClientDownloadResult resultArtifact =
- downloadTheArtifact(artifact, notificationData);
+ downloadTheArtifact(artifact, notificationData);
final var filePath = writeArtifactToFile(artifact, resultArtifact);
final var csarObject = new Csar(filePath.toString());
inputReceived(csarObject);
sendDistributionStatus(DistributionStatusType.DEPLOY, artifact.getArtifactURL(),
- notificationData.getDistributionID(), DistributionStatusEnum.DEPLOY_OK, null);
+ notificationData.getDistributionID(), DistributionStatusEnum.DEPLOY_OK, null);
deleteArtifactFile(filePath);
} catch (final ArtifactDownloadException | PolicyDecodingException exp) {
LOGGER.error("Failed to process csar service artifacts ", exp);
artifactsProcessedSuccessfully = false;
sendDistributionStatus(DistributionStatusType.DEPLOY, artifact.getArtifactURL(),
- notificationData.getDistributionID(), DistributionStatusEnum.DEPLOY_ERROR,
- "Failed to deploy the artifact due to: " + exp.getMessage());
+ notificationData.getDistributionID(), DistributionStatusEnum.DEPLOY_ERROR,
+ "Failed to deploy the artifact due to: " + exp.getMessage());
}
}
if (artifactsProcessedSuccessfully) {
DistributionStatisticsManager.updateDistributionSuccessCount();
sendComponentDoneStatus(notificationData.getDistributionID(), DistributionStatusEnum.COMPONENT_DONE_OK,
- null);
+ null);
} else {
DistributionStatisticsManager.updateDistributionFailureCount();
sendComponentDoneStatus(notificationData.getDistributionID(), DistributionStatusEnum.COMPONENT_DONE_ERROR,
- "Failed to process the artifact");
+ "Failed to process the artifact");
}
}
@@ -233,38 +231,42 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
* @throws ArtifactDownloadException if download fails
*/
private IDistributionClientDownloadResult downloadTheArtifact(final IArtifactInfo artifact,
- final INotificationData notificationData) throws ArtifactDownloadException {
+ final INotificationData notificationData)
+ throws ArtifactDownloadException {
DistributionStatisticsManager.updateTotalDownloadCount();
final IDistributionClientDownloadResult downloadResult = distributionClient.download(artifact);
if (!downloadResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
DistributionStatisticsManager.updateDownloadFailureCount();
final String message = "Failed to download artifact with name: " + artifact.getArtifactName() + " due to: "
- + downloadResult.getDistributionMessageResult();
+ + downloadResult.getDistributionMessageResult();
LOGGER.error(message);
sendDistributionStatus(DistributionStatusType.DOWNLOAD, artifact.getArtifactURL(),
- notificationData.getDistributionID(), DistributionStatusEnum.DOWNLOAD_ERROR, message);
+ notificationData.getDistributionID(), DistributionStatusEnum.DOWNLOAD_ERROR, message);
throw new ArtifactDownloadException(message);
}
DistributionStatisticsManager.updateDownloadSuccessCount();
sendDistributionStatus(DistributionStatusType.DOWNLOAD, artifact.getArtifactURL(),
- notificationData.getDistributionID(), DistributionStatusEnum.DOWNLOAD_OK, null);
+ notificationData.getDistributionID(), DistributionStatusEnum.DOWNLOAD_OK, null);
return downloadResult;
}
/**
* Method to write the downloaded distribution artifact to local file system.
*
- * @param artifact the notification artifact
+ * @param artifact the notification artifact
* @param resultArtifact the download result artifact
* @return the local path of written file
* @throws ArtifactDownloadException if error occurs while writing the artifact
*/
private Path writeArtifactToFile(final IArtifactInfo artifact,
- final IDistributionClientDownloadResult resultArtifact) throws ArtifactDownloadException {
+ final IDistributionClientDownloadResult resultArtifact)
+ throws ArtifactDownloadException {
try {
final byte[] payloadBytes = resultArtifact.getArtifactPayload();
- final var tempArtifactFile = File.createTempFile(artifact.getArtifactName(), ".csar");
+
+ final var tempArtifactFile = Optional.ofNullable(safelyCreateFile(artifact.getArtifactName()))
+ .orElseThrow(() -> new ArtifactDownloadException("Failed to create temporary file."));
try (var fileOutputStream = new FileOutputStream(tempArtifactFile)) {
fileOutputStream.write(payloadBytes, 0, payloadBytes.length);
return tempArtifactFile.toPath();
@@ -290,19 +292,20 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
/**
* Sends the distribution status to SDC using the input values.
*
- * @param statusType the status type
- * @param artifactUrl the artifact url
+ * @param statusType the status type
+ * @param artifactUrl the artifact url
* @param distributionId the distribution id
- * @param status the status
- * @param errorReason the error reason
+ * @param status the status
+ * @param errorReason the error reason
*/
private void sendDistributionStatus(final DistributionStatusType statusType, final String artifactUrl,
- final String distributionId, final DistributionStatusEnum status, final String errorReason) {
+ final String distributionId, final DistributionStatusEnum status,
+ final String errorReason) {
IDistributionClientResult clientResult;
final IDistributionStatusMessage message = DistributionStatusMessage.builder().artifactUrl(artifactUrl)
- .consumerId(sdcConfig.getConsumerID()).distributionId(distributionId).distributionStatus(status)
- .timestamp(System.currentTimeMillis()).build();
+ .consumerId(sdcConfig.getConsumerID()).distributionId(distributionId).distributionStatus(status)
+ .timestamp(System.currentTimeMillis()).build();
if (DistributionStatusType.DOWNLOAD.equals(statusType)) {
if (errorReason != null) {
clientResult = distributionClient.sendDownloadStatus(message, errorReason);
@@ -318,8 +321,8 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
}
final var loggerMessage = new StringBuilder();
loggerMessage.append("distribution status to SDC with values - ").append("DistributionId")
- .append(distributionId).append(" Artifact: ").append(artifactUrl).append(" StatusType: ")
- .append(statusType.name()).append(" Status: ").append(status.name());
+ .append(distributionId).append(" Artifact: ").append(artifactUrl).append(" StatusType: ")
+ .append(statusType.name()).append(" Status: ").append(status.name());
if (errorReason != null) {
loggerMessage.append(" ErrorReason: ").append(errorReason);
}
@@ -336,15 +339,15 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
* Sends the component done status to SDC using the input values.
*
* @param distributionId the distribution Id
- * @param status the distribution status
- * @param errorReason the error reason
+ * @param status the distribution status
+ * @param errorReason the error reason
*/
private void sendComponentDoneStatus(final String distributionId, final DistributionStatusEnum status,
- final String errorReason) {
+ final String errorReason) {
IDistributionClientResult clientResult;
final IComponentDoneStatusMessage message = ComponentDoneStatusMessage.builder()
- .consumerId(sdcConfig.getConsumerID()).distributionId(distributionId).distributionStatus(status)
- .timestamp(System.currentTimeMillis()).build();
+ .consumerId(sdcConfig.getConsumerID()).distributionId(distributionId).distributionStatus(status)
+ .timestamp(System.currentTimeMillis()).build();
if (errorReason == null) {
clientResult = distributionClient.sendComponentDoneStatus(message);
} else {
@@ -353,7 +356,7 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
final var loggerMessage = new StringBuilder();
loggerMessage.append("component done status to SDC with values - ").append("DistributionId")
- .append(distributionId).append(" Status: ").append(status.name());
+ .append(distributionId).append(" Status: ").append(status.name());
if (errorReason != null) {
loggerMessage.append(" ErrorReason: ").append(errorReason);
}
@@ -374,4 +377,13 @@ public class SdcReceptionHandler extends AbstractReceptionHandler implements INo
sdcReceptionHandlerStatus = newStatus;
}
}
+
+ private File safelyCreateFile(String prefix) throws IOException {
+ File file = Files.createTempFile(prefix, ".csar").toFile();
+ if (file.setReadable(true, false)
+ && file.setWritable(true, true)) {
+ return file;
+ }
+ return null;
+ }
}
diff --git a/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/util/ReceptionUtil.java b/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/util/ReceptionUtil.java
index c26286da..6b0c762a 100644
--- a/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/util/ReceptionUtil.java
+++ b/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/util/ReceptionUtil.java
@@ -20,9 +20,13 @@
package org.onap.policy.distribution.reception.util;
+import java.io.BufferedInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InvalidClassException;
import java.nio.file.Path;
+import java.util.Enumeration;
+import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.onap.policy.common.utils.coder.CoderException;
@@ -44,25 +48,20 @@ public class ReceptionUtil {
private static final StandardCoder coder = new StandardCoder();
private static final StandardYamlCoder yamlCoder = new StandardYamlCoder();
- private static final long MAX_FILE_SIZE = 512L * 1024;
+ private static final long THRESHOLD_SIZE = 512L * 1024;
+ private static final int THRESHOLD_ENTRIES = 10000;
+ private static final double THRESHOLD_RATIO = 20;
/**
* Method to ensure validation of entries in the Zipfile. Attempts to solve path
* injection java security issues.
*
* @param entryName name of the ZipEntry to check
- * @param csarPath Absolute path to the csar the ZipEntry is in
- * @param entrySize size of the ZipEntry
+ * @param csarPath Absolute path to the csar the ZipEntry is in
* @throws PolicyDecodingException if the file size is too large
*/
- public static void validateZipEntry(String entryName, String csarPath, long entrySize)
- throws PolicyDecodingException {
- //
- // Check file size
- //
- if (entrySize > MAX_FILE_SIZE) {
- throw new PolicyDecodingException("Zip entry for " + entryName + " is too large " + entrySize);
- }
+ public static void validateZipEntry(String entryName, String csarPath)
+ throws PolicyDecodingException {
//
// Now ensure that there is no path injection
//
@@ -78,19 +77,85 @@ public class ReceptionUtil {
/**
* Method to decode either a json or yaml file into an object.
*
- * @param zipFile the zip file
- * @param entry the entry to read in the zip file.
+ * @param zipEntryName the zip file name.
+ * @param entryData the data from entry to decode.
* @return the decoded ToscaServiceTemplate object.
* @throws CoderException IOException if the file decoding fails.
*/
- public static ToscaServiceTemplate decodeFile(ZipFile zipFile, final ZipEntry entry)
- throws IOException, CoderException {
+ public static ToscaServiceTemplate decodeFile(String zipEntryName, InputStream entryData) throws CoderException {
ToscaServiceTemplate toscaServiceTemplate = null;
- if (entry.getName().endsWith(".json")) {
- toscaServiceTemplate = coder.decode(zipFile.getInputStream(entry), ToscaServiceTemplate.class);
- } else if (entry.getName().endsWith(".yml")) {
- toscaServiceTemplate = yamlCoder.decode(zipFile.getInputStream(entry), ToscaServiceTemplate.class);
+ if (zipEntryName.endsWith(".json")) {
+ toscaServiceTemplate = coder.decode(entryData, ToscaServiceTemplate.class);
+ } else if (zipEntryName.endsWith(".yml")) {
+ toscaServiceTemplate = yamlCoder.decode(entryData, ToscaServiceTemplate.class);
}
return toscaServiceTemplate;
}
+
+ /**
+ * Unzip the csar file following the security recommendations from sonar cloud to avoid a zip bomb attack.
+ *
+ * @param csarFilename csar file which is a zip file.
+ * @param unzippedTemplates the templates which should be unzipped.
+ * @param filter contains the keywords for the entry name.
+ * @throws PolicyDecodingException in case zip file can't be read
+ * @throws CoderException in case files can't be decoded to a template
+ */
+ public static void unzip(String csarFilename, Map<String, ToscaServiceTemplate> unzippedTemplates, String... filter)
+ throws PolicyDecodingException, CoderException {
+ try (var zipFile = new ZipFile(csarFilename)) {
+ int totalSizeArchive = 0;
+ int totalEntryArchive = 0;
+
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ totalEntryArchive++;
+
+ if (checkEntryFilter(entry.getName(), filter)) {
+ validateZipEntry(entry.getName(), csarFilename);
+ InputStream entryData = new BufferedInputStream(zipFile.getInputStream(entry));
+
+ int bufferedBytes;
+ byte[] buffer = new byte[2048];
+ int totalSizeEntry = 0;
+
+ boolean isValidThreshold = true;
+ while ((bufferedBytes = entryData.read(buffer)) > 0 && isValidThreshold) {
+ totalSizeEntry += bufferedBytes;
+ totalSizeArchive += bufferedBytes;
+
+ double compressionRatio = Math.floorDiv(totalSizeEntry, entry.getCompressedSize());
+ isValidThreshold = compressionRatio <= THRESHOLD_RATIO;
+ }
+
+ unzippedTemplates.put(entry.getName(), decodeFile(entry.getName(), zipFile.getInputStream(entry)));
+ }
+
+ if (totalSizeArchive > THRESHOLD_SIZE || totalEntryArchive > THRESHOLD_ENTRIES) {
+ // the uncompressed data size is too much for the application resource capacity
+ break;
+ }
+ }
+ } catch (IOException exception) {
+ throw new PolicyDecodingException("Couldn't read the zipFile", exception);
+ }
+ }
+
+ /**
+ * Check if entry is the one to be unzipped based on the filter.
+ *
+ * @param entryName zip file entry name.
+ * @param filter the list of filter to be looked up on entry names.
+ * @return true if entry is in filter, false otherwise.
+ */
+ public static boolean checkEntryFilter(String entryName, String... filter) {
+ for (String f : filter) {
+ if (entryName.contains(f)) {
+ return true;
+ }
+ }
+ return false;
+ }
}