Large csar handling - object store 67/124767/5
authorvasraz <vasyl.razinkov@est.tech>
Fri, 8 Oct 2021 13:48:08 +0000 (14:48 +0100)
committerAndr� Schmid <andre.schmid@est.tech>
Fri, 5 Nov 2021 20:28:52 +0000 (20:28 +0000)
Change-Id: I4e88bd7bfcc1fdbc93d67da2682f2e873ba243c6
Signed-off-by: Vasyl Razinkov <vasyl.razinkov@est.tech>
Issue-ID: SDC-3754

28 files changed:
common-app-api/src/main/java/org/openecomp/sdc/be/csar/storage/ArtifactInfo.java
common-app-api/src/main/java/org/openecomp/sdc/be/csar/storage/ArtifactStorageConfig.java
common-app-api/src/main/java/org/openecomp/sdc/be/csar/storage/ArtifactStorageManager.java
common-be/pom.xml
common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoArtifactInfo.java [moved from common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentStorageArtifactInfo.java with 78% similarity]
common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageConfig.java [moved from common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageConfig.java with 61% similarity]
common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageManager.java [new file with mode: 0644]
common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageCsarSizeReducer.java [moved from common-be/src/main/java/org/openecomp/sdc/be/csar/storage/CsarSizeReducer.java with 98% similarity]
common-be/src/main/java/org/openecomp/sdc/be/csar/storage/NoneStorageManager.java [new file with mode: 0644]
common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageManager.java [deleted file]
common-be/src/main/java/org/openecomp/sdc/be/csar/storage/StorageFactory.java [new file with mode: 0644]
common-be/src/main/java/org/openecomp/sdc/be/csar/storage/exception/ArtifactStorageException.java [moved from common-be/src/main/java/org/openecomp/sdc/be/csar/storage/exception/PersistentVolumeArtifactStorageException.java with 80% similarity]
common-be/src/test/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageManagerTest.java [new file with mode: 0644]
common-be/src/test/java/org/openecomp/sdc/be/csar/storage/MinIoStorageCsarSizeReducerTest.java [moved from common-be/src/test/java/org/openecomp/sdc/be/csar/storage/CsarSizeReducerTest.java with 93% similarity]
common-be/src/test/java/org/openecomp/sdc/be/csar/storage/NoneStorageManagerTest.java [new file with mode: 0644]
common-be/src/test/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageManagerTest.java [deleted file]
common-be/src/test/resources/csarSizeReducer/dummyToReduce-2-files.zip [new file with mode: 0644]
common-be/src/test/resources/csarSizeReducer/dummyToReduce-3-files.zip [moved from common-be/src/test/resources/csarSizeReducer/dummyToReduce.zip with 100% similarity]
common-be/src/test/resources/s3StoreArtifactStorageManager/dummy.csar [new file with mode: 0644]
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/services/OrchestrationTemplateCandidateImpl.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/test/java/org/openecomp/sdcrests/vsp/rest/services/OrchestrationTemplateCandidateImplTest.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/CsarSecurityValidator.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/security/SecurityManager.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/CsarSecurityValidatorTest.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/security/SecurityManagerTest.java
openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/configuration.yaml.erb
openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/errors/Messages.java
openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/dao/impl/zusammen/OrchestrationTemplateCandidateDaoZusammenImpl.java

index 7584770..9142653 100644 (file)
 
 package org.openecomp.sdc.be.csar.storage;
 
-import java.nio.file.Path;
-
 /**
  * Represents the stored artifact
  */
 public interface ArtifactInfo {
 
-    Path getPath();
+    String getInfo();
 
 }
index da06db0..0a4f355 100644 (file)
@@ -52,6 +52,16 @@ public interface ArtifactStorageManager {
      *
      * @return {@code true} if enable, {@code false} otherwise
      */
-    boolean isEnabled();
+    default boolean isEnabled() {
+        return false;
+    }
 
+    /**
+     * @return Storage Configuration
+     */
+    ArtifactStorageConfig getStorageConfiguration();
+
+    InputStream get(final ArtifactInfo artifactInfo);
+
+    void delete(ArtifactInfo artifactInfo);
 }
index af93628..d84eec5 100644 (file)
 <project xmlns="http://maven.apache.org/POM/4.0.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-
-  <groupId>org.openecomp.sdc.be</groupId>
-  <artifactId>common-be</artifactId>
-
-  <parent>
-    <groupId>org.openecomp.sdc</groupId>
-    <artifactId>sdc-main</artifactId>
-    <version>1.10.0-SNAPSHOT</version>
-  </parent>
-
-  <dependencies>
-
-    <dependency>
-      <groupId>com.fasterxml.jackson.core</groupId>
-      <artifactId>jackson-core</artifactId>
-      <version>${jackson.version}</version>
-    </dependency>
-
-    <!-- Common of SD&C -->
-    <dependency>
-      <groupId>org.openecomp.sdc</groupId>
-      <artifactId>common-app-api</artifactId>
-      <version>${project.version}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.core</groupId>
-          <artifactId>jackson-core</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>commons-codec</groupId>
-          <artifactId>commons-codec</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-
-    <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-lang3</artifactId>
-      <version>${lang3.version}</version>
-      <scope>provided</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>ch.qos.logback</groupId>
-      <artifactId>logback-classic</artifactId>
-      <version>${logback.version}</version>
-      <scope>provided</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>com.google.guava</groupId>
-      <artifactId>guava</artifactId>
-      <version>${guava.version}</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.functionaljava</groupId>
-      <artifactId>functionaljava</artifactId>
-      <version>${functionaljava.version}</version>
-      <scope>provided</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>com.fasterxml.jackson.core</groupId>
-      <artifactId>jackson-databind</artifactId>
-      <version>${jackson.version}</version>
-      <scope>provided</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.core</groupId>
-          <artifactId>jackson-core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-
-    <dependency>
-      <groupId>org.bouncycastle</groupId>
-      <artifactId>bcpkix-jdk15on</artifactId>
-      <version>${bouncycastle.version}</version>
-      <scope>compile</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>org.hamcrest</groupId>
-      <artifactId>hamcrest</artifactId>
-      <version>${hamcrest.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.hamcrest</groupId>
-      <artifactId>hamcrest-library</artifactId>
-      <version>${hamcrest.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.junit.jupiter</groupId>
-      <artifactId>junit-jupiter</artifactId>
-      <version>${junitJupiter.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.mockito</groupId>
-      <artifactId>mockito-junit-jupiter</artifactId>
-      <version>${mockitoJupiter.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.onap.sdc.common</groupId>
-      <artifactId>onap-tosca-datatype</artifactId>
-      <version>${tosca.datatype.version}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.core</groupId>
-          <artifactId>jackson-core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.projectlombok</groupId>
-      <artifactId>lombok</artifactId>
-      <version>${lombok.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.google.code.bean-matchers</groupId>
-      <artifactId>bean-matchers</artifactId>
-      <version>${bean-matchers.version}</version>
-      <scope>test</scope>
-    </dependency>
-
-    <!-- Togglz core module (mandatory) -->
-    <dependency>
-      <groupId>org.togglz</groupId>
-      <artifactId>togglz-core</artifactId>
-      <version>${togglz.version}</version>
-    </dependency>
-
-    <!-- Togglz for Servlet environments (mandatory for webapps) -->
-    <dependency>
-      <groupId>org.togglz</groupId>
-      <artifactId>togglz-servlet</artifactId>
-      <version>${togglz.version}</version>
-    </dependency>
-
-    <!-- Togglz Admin Console -->
-    <dependency>
-      <groupId>org.togglz</groupId>
-      <artifactId>togglz-console</artifactId>
-      <version>${togglz.version}</version>
-    </dependency>
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.openecomp.sdc.be</groupId>
+    <artifactId>common-be</artifactId>
+
+    <parent>
+        <groupId>org.openecomp.sdc</groupId>
+        <artifactId>sdc-main</artifactId>
+        <version>1.10.0-SNAPSHOT</version>
+    </parent>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>${jackson.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.minio</groupId>
+            <artifactId>minio</artifactId>
+            <version>8.3.0</version>
+        </dependency>
+
+        <!-- Common of SD&C -->
+        <dependency>
+            <groupId>org.openecomp.sdc</groupId>
+            <artifactId>common-app-api</artifactId>
+            <version>${project.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>commons-codec</groupId>
+                    <artifactId>commons-codec</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>${lang3.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>${logback.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>${guava.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.functionaljava</groupId>
+            <artifactId>functionaljava</artifactId>
+            <version>${functionaljava.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>${jackson.version}</version>
+            <scope>provided</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcpkix-jdk15on</artifactId>
+            <version>${bouncycastle.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <version>${hamcrest.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-library</artifactId>
+            <version>${hamcrest.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <version>${junitJupiter.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-junit-jupiter</artifactId>
+            <version>${mockitoJupiter.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.sdc.common</groupId>
+            <artifactId>onap-tosca-datatype</artifactId>
+            <version>${tosca.datatype.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>${lombok.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.bean-matchers</groupId>
+            <artifactId>bean-matchers</artifactId>
+            <version>${bean-matchers.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- Togglz core module (mandatory) -->
+        <dependency>
+            <groupId>org.togglz</groupId>
+            <artifactId>togglz-core</artifactId>
+            <version>${togglz.version}</version>
+        </dependency>
+
+        <!-- Togglz for Servlet environments (mandatory for webapps) -->
+        <dependency>
+            <groupId>org.togglz</groupId>
+            <artifactId>togglz-servlet</artifactId>
+            <version>${togglz.version}</version>
+        </dependency>
+
+        <!-- Togglz Admin Console -->
+        <dependency>
+            <groupId>org.togglz</groupId>
+            <artifactId>togglz-console</artifactId>
+            <version>${togglz.version}</version>
+        </dependency>
 
         <!-- Togglz for testing -->
         <dependency>
             <version>${togglz.version}</version>
             <scope>test</scope>
         </dependency>
-    <dependency>
-      <groupId>org.springframework</groupId>
-      <artifactId>spring-context</artifactId>
-      <version>${spring.version}</version>
-      <scope>compile</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>org.springframework</groupId>
-          <artifactId>spring-expression</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.springframework</groupId>
-          <artifactId>spring-core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.springframework</groupId>
-      <artifactId>spring-core</artifactId>
-      <version>${spring.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.cxf</groupId>
-      <artifactId>cxf-rt-frontend-jaxrs</artifactId>
-      <version>${cxf.version}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.jboss.spec.javax.rmi</groupId>
-          <artifactId>jboss-rmi-api_1.0_spec</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <artifactId>maven-jar-plugin</artifactId>
-        <version>${maven-jar-plugin.version}</version>
-        <executions>
-          <execution>
-            <id>default-jar</id>
-            <phase>package</phase>
-            <goals>
-              <goal>jar</goal>
-              <goal>test-jar</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>com.github.sylvainlaurent.maven</groupId>
-        <artifactId>yaml-json-validator-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>validate</id>
-            <phase>validate</phase>
-            <goals>
-              <goal>validate</goal>
-            </goals>
-            <configuration>
-              <validationSets>
-                <validationSet>
-                  <includes>
-                    <include>src/main/resources/**/*.y*ml</include>
-                    <include>src/test/resources/**/*.y*ml</include>
-                  </includes>
-                </validationSet>
-                <validationSet>
-                  <includes>
-                    <include>src/main/resources/**/*.json</include>
-                    <include>src/test/resources/**/*.json</include>
-                  </includes>
-                </validationSet>
-              </validationSets>
-              <skip>${skipYamlJsonValidator}</skip>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <version>${spring.version}</version>
+            <scope>compile</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework</groupId>
+                    <artifactId>spring-expression</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.springframework</groupId>
+                    <artifactId>spring-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>${cxf.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.jboss.spec.javax.rmi</groupId>
+                    <artifactId>jboss-rmi-api_1.0_spec</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.openecomp.sdc.core</groupId>
+            <artifactId>openecomp-common-lib</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>${maven-jar-plugin.version}</version>
+                <executions>
+                    <execution>
+                        <id>default-jar</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>jar</goal>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>com.github.sylvainlaurent.maven</groupId>
+                <artifactId>yaml-json-validator-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>validate</id>
+                        <phase>validate</phase>
+                        <goals>
+                            <goal>validate</goal>
+                        </goals>
+                        <configuration>
+                            <validationSets>
+                                <validationSet>
+                                    <includes>
+                                        <include>src/main/resources/**/*.y*ml</include>
+                                        <include>src/test/resources/**/*.y*ml</include>
+                                    </includes>
+                                </validationSet>
+                                <validationSet>
+                                    <includes>
+                                        <include>src/main/resources/**/*.json</include>
+                                        <include>src/test/resources/**/*.json</include>
+                                    </includes>
+                                </validationSet>
+                            </validationSets>
+                            <skip>${skipYamlJsonValidator}</skip>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>
 
 package org.openecomp.sdc.be.csar.storage;
 
-import java.nio.file.Path;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 
 @AllArgsConstructor
-public class PersistentStorageArtifactInfo implements ArtifactInfo {
+@Getter
+public class MinIoArtifactInfo implements ArtifactInfo {
 
-    @Getter
-    private final Path path;
+    private final String bucket;
+    private final String objectName;
 
+    @Override
+    public String getInfo() {
+        return String.format("bucket: %s\n"
+            + "object: %s", bucket, objectName);
+    }
 }
 
 package org.openecomp.sdc.be.csar.storage;
 
-import java.nio.file.Path;
-import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
 
-@Data
-public class PersistentVolumeArtifactStorageConfig implements ArtifactStorageConfig {
+@AllArgsConstructor
+@Getter
+public class MinIoStorageArtifactStorageConfig implements ArtifactStorageConfig {
 
     private final boolean isEnabled;
-    private final Path storagePath;
+    private final EndPoint endPoint;
+    private final Credentials credentials;
+    private final String tempPath;
+
+    @AllArgsConstructor
+    @Getter
+    public static class EndPoint {
+
+        private final String host;
+        private final int port;
+        private final boolean secure;
+    }
+
+    @AllArgsConstructor
+    @Getter
+    public static class Credentials {
+
+        private final String accessKey;
+        private final String secretKey;
+    }
 
 }
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageManager.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageManager.java
new file mode 100644 (file)
index 0000000..0a48c22
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.storage;
+
+import static org.openecomp.sdc.common.errors.Messages.EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING;
+
+import io.minio.BucketExistsArgs;
+import io.minio.CopyObjectArgs;
+import io.minio.CopySource;
+import io.minio.GetObjectArgs;
+import io.minio.MakeBucketArgs;
+import io.minio.MinioClient;
+import io.minio.MinioClient.Builder;
+import io.minio.PutObjectArgs;
+import io.minio.RemoveObjectArgs;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import lombok.Getter;
+import org.openecomp.sdc.be.csar.storage.MinIoStorageArtifactStorageConfig.Credentials;
+import org.openecomp.sdc.be.csar.storage.MinIoStorageArtifactStorageConfig.EndPoint;
+import org.openecomp.sdc.be.csar.storage.exception.ArtifactStorageException;
+import org.openecomp.sdc.common.CommonConfigurationManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MinIoStorageArtifactStorageManager implements ArtifactStorageManager {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(MinIoStorageArtifactStorageManager.class);
+    private static final String EXTERNAL_CSAR_STORE = "externalCsarStore";
+
+    @Getter
+    private final MinIoStorageArtifactStorageConfig storageConfiguration;
+    private final MinioClient minioClient;
+
+    public MinIoStorageArtifactStorageManager() {
+        this.storageConfiguration = readMinIoStorageArtifactStorageConfig();
+        minioClient = initMinioClient();
+    }
+
+    //for testing only
+    MinIoStorageArtifactStorageManager(final ArtifactStorageConfig storageConfiguration) {
+        this.storageConfiguration = (MinIoStorageArtifactStorageConfig) storageConfiguration;
+        minioClient = initMinioClient();
+    }
+
+    @Override
+    public ArtifactInfo persist(final String vspId, final String versionId, final ArtifactInfo uploadedArtifactInfo) {
+        final MinIoArtifactInfo minioObjectTemp = (MinIoArtifactInfo) uploadedArtifactInfo;
+        try {
+            minioClient.getObject(
+                GetObjectArgs.builder()
+                    .bucket(minioObjectTemp.getBucket())
+                    .object(minioObjectTemp.getObjectName())
+                    .build()
+            );
+        } catch (final Exception e) {
+            throw new ArtifactStorageException(
+                String.format("Failed to retrieve uploaded artifact with bucket '%s' and name '%s' while persisting",
+                    minioObjectTemp.getBucket(), minioObjectTemp.getObjectName()), e);
+        }
+
+        final var backupPath = backupPreviousVersion(vspId, versionId).orElse(null);
+        try {
+            moveFile(minioObjectTemp, vspId, versionId);
+        } catch (final Exception e) {
+            rollback(minioObjectTemp, vspId, versionId);
+            final var errorMsg = String.format("Could not persist artifact for VSP '%s', version '%s'", vspId, versionId);
+            throw new ArtifactStorageException(errorMsg, e);
+        }
+
+        removePreviousVersion(backupPath);
+
+        return new MinIoArtifactInfo(vspId, versionId);
+    }
+
+    @Override
+    public ArtifactInfo upload(final String vspId, final String versionId, final InputStream fileToUpload) {
+
+        final String name = versionId + "--" + UUID.randomUUID();
+        try {
+            // Make bucket if not exist.
+            final boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(vspId).build());
+
+            if (!found) {
+                // Make a new bucket ${vspId} .
+                minioClient.makeBucket(MakeBucketArgs.builder().bucket(vspId).build());
+            } else {
+                LOGGER.info("Bucket '{}' already exists.", vspId);
+            }
+
+            minioClient.putObject(
+                PutObjectArgs.builder()
+                    .bucket(vspId)
+                    .object(name)
+                    .stream(fileToUpload, fileToUpload.available(), -1)
+                    .build()
+            );
+
+        } catch (final Exception e) {
+            throw new ArtifactStorageException("Failed to upload artifact", e);
+        }
+
+        return new MinIoArtifactInfo(vspId, name);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return storageConfiguration != null && storageConfiguration.isEnabled();
+    }
+
+    @Override
+    public InputStream get(final ArtifactInfo artifactInfo) {
+        final MinIoArtifactInfo minioObject = (MinIoArtifactInfo) artifactInfo;
+        try {
+            return minioClient.getObject(GetObjectArgs.builder()
+                .bucket(minioObject.getBucket())
+                .object(minioObject.getObjectName())
+                .build());
+        } catch (final Exception e) {
+            throw new ArtifactStorageException("Failed to get Object", e);
+        }
+    }
+
+    @Override
+    public void delete(final ArtifactInfo artifactInfo) {
+        final MinIoArtifactInfo minioObject = (MinIoArtifactInfo) artifactInfo;
+        try {
+            minioClient.removeObject(RemoveObjectArgs.builder()
+                .bucket(minioObject.getBucket())
+                .object(minioObject.getObjectName())
+                .bypassGovernanceMode(true)
+                .build());
+        } catch (final Exception e) {
+            throw new ArtifactStorageException(String.format("Failed to delete '%s'", minioObject.getObjectName()), e);
+        }
+
+    }
+
+    private Optional<MinIoArtifactInfo> backupPreviousVersion(final String vspId, final String versionId) {
+
+        final String tempName = versionId + "--" + UUID.randomUUID().toString();
+        try {
+            copy(vspId, tempName, versionId);
+        } catch (final Exception e) {
+            return Optional.empty();
+        }
+
+        return Optional.of(new MinIoArtifactInfo(vspId, tempName));
+    }
+
+    private void rollback(final MinIoArtifactInfo minioObject, final String vspId, final String versionId) {
+        try {
+            moveFile(minioObject, vspId, versionId);
+        } catch (final Exception ex) {
+            LOGGER.warn("Could not rollback the backup '{}' to the original '{}'", versionId, minioObject.getObjectName(), ex);
+        }
+    }
+
+    private void removePreviousVersion(final MinIoArtifactInfo minioObject) {
+        if (minioObject == null) {
+            return;
+        }
+        delete(minioObject);
+    }
+
+    private void moveFile(final MinIoArtifactInfo minioObject, final String vspId, final String versionId) {
+        try {
+            copy(vspId, versionId, minioObject.getObjectName());
+        } catch (final Exception e) {
+            throw new ArtifactStorageException("Failed to move", e);
+        }
+        delete(minioObject);
+    }
+
+    private void copy(final String vspId, final String versionId, final String objectName) throws Exception {
+        minioClient.copyObject(
+            CopyObjectArgs.builder()
+                .bucket(vspId)
+                .object(versionId)
+                .source(CopySource.builder()
+                    .bucket(vspId)
+                    .object(objectName)
+                    .build())
+                .build());
+    }
+
+    private MinIoStorageArtifactStorageConfig readMinIoStorageArtifactStorageConfig() {
+        final var commonConfigurationManager = CommonConfigurationManager.getInstance();
+
+        final Map<String, Object> endpoint = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "endpoint", null);
+        final Map<String, Object> credentials = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "credentials", null);
+        final String tempPath = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "tempPath", null);
+        LOGGER.info("ArtifactConfig.endpoint: '{}'", endpoint);
+        LOGGER.info("ArtifactConfig.credentials: '{}'", credentials);
+        LOGGER.info("ArtifactConfig.tempPath: '{}'", tempPath);
+
+        if (endpoint == null) {
+            throw new RuntimeException(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage("endpoint"));
+        }
+        if (credentials == null) {
+            throw new RuntimeException(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage("credentials"));
+        }
+        if (tempPath == null) {
+            throw new RuntimeException(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage("tempPath"));
+        }
+        final String host = (String) endpoint.getOrDefault("host", null);
+        final int port = (int) endpoint.getOrDefault("port", 0);
+        final boolean secure = (boolean) endpoint.getOrDefault("secure", false);
+
+        final String accessKey = (String) credentials.getOrDefault("accessKey", null);
+        final String secretKey = (String) credentials.getOrDefault("secretKey", null);
+
+        return new MinIoStorageArtifactStorageConfig(true, new EndPoint(host, port, secure), new Credentials(accessKey, secretKey), tempPath);
+    }
+
+    private MinioClient initMinioClient() {
+        final EndPoint endPoint = storageConfiguration.getEndPoint();
+        final Credentials credentials = storageConfiguration.getCredentials();
+
+        final Builder builder = MinioClient.builder();
+        return builder
+            .endpoint(endPoint.getHost(), endPoint.getPort(), endPoint.isSecure())
+            .credentials(credentials.getAccessKey(), credentials.getSecretKey())
+            .build();
+    }
+
+}
@@ -43,9 +43,9 @@ import org.openecomp.sdc.be.csar.storage.exception.CsarSizeReducerException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class CsarSizeReducer implements PackageSizeReducer {
+public class MinIoStorageCsarSizeReducer implements PackageSizeReducer {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(CsarSizeReducer.class);
+    private static final Logger LOGGER = LoggerFactory.getLogger(MinIoStorageCsarSizeReducer.class);
     private static final Set<String> ALLOWED_SIGNATURE_EXTENSIONS = Set.of("cms");
     private static final Set<String> ALLOWED_CERTIFICATE_EXTENSIONS = Set.of("cert", "crt");
     private static final String CSAR_EXTENSION = "csar";
@@ -55,7 +55,7 @@ public class CsarSizeReducer implements PackageSizeReducer {
 
     private final CsarPackageReducerConfiguration configuration;
 
-    public CsarSizeReducer(final CsarPackageReducerConfiguration configuration) {
+    public MinIoStorageCsarSizeReducer(final CsarPackageReducerConfiguration configuration) {
         this.configuration = configuration;
     }
 
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/NoneStorageManager.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/NoneStorageManager.java
new file mode 100644 (file)
index 0000000..3fa22d4
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.storage;
+
+import java.io.InputStream;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+public class NoneStorageManager implements ArtifactStorageManager {
+
+    @Override
+    public ArtifactInfo persist(final String vspId, final String versionId, final ArtifactInfo uploadedArtifactInfo) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ArtifactInfo upload(final String vspId, final String versionId, final InputStream fileToUpload) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ArtifactStorageConfig getStorageConfiguration() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public InputStream get(final ArtifactInfo artifactInfo) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void delete(final ArtifactInfo artifactInfo) {
+        throw new UnsupportedOperationException();
+    }
+
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageManager.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageManager.java
deleted file mode 100644 (file)
index 10629b3..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
- *  ================================================================================
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  SPDX-License-Identifier: Apache-2.0
- *  ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.be.csar.storage;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.util.Optional;
-import java.util.UUID;
-import org.openecomp.sdc.be.csar.storage.exception.PersistentVolumeArtifactStorageException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class PersistentVolumeArtifactStorageManager implements ArtifactStorageManager {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(PersistentVolumeArtifactStorageManager.class);
-
-    private final PersistentVolumeArtifactStorageConfig storageConfiguration;
-
-    public PersistentVolumeArtifactStorageManager(final ArtifactStorageConfig storageConfiguration) {
-        this.storageConfiguration = (PersistentVolumeArtifactStorageConfig) storageConfiguration;
-    }
-
-    @Override
-    public ArtifactInfo persist(final String vspId, final String versionId, final ArtifactInfo uploadedArtifactInfo) {
-        final var temporaryPath = uploadedArtifactInfo.getPath();
-        if (!Files.exists(temporaryPath)) {
-            throw new PersistentVolumeArtifactStorageException(String.format("Given artifact does not exist '%s'", uploadedArtifactInfo.getPath()));
-        }
-
-        final var filePath = buildFilePath(vspId, versionId);
-        final var backupPath = backupPreviousVersion(filePath).orElse(null);
-        try {
-            moveFile(temporaryPath, filePath);
-        } catch (final Exception e) {
-            rollback(backupPath, filePath);
-            final var errorMsg = String.format("Could not persist artifact for VSP '%s', version '%s'", vspId, versionId);
-            throw new PersistentVolumeArtifactStorageException(errorMsg, e);
-        }
-
-        removePreviousVersion(backupPath);
-
-        return new PersistentStorageArtifactInfo(filePath);
-    }
-
-    @Override
-    public ArtifactInfo upload(final String vspId, final String versionId, final InputStream artifactInputStream) {
-        final var destinationFolder = buildDestinationFolder(vspId, versionId);
-        try {
-            Files.createDirectories(destinationFolder);
-        } catch (final IOException e) {
-            throw new PersistentVolumeArtifactStorageException(String.format("Could not create directory '%s'", destinationFolder), e);
-        }
-
-        final var filePath = createTempFilePath(destinationFolder);
-        try {
-            persist(artifactInputStream, filePath);
-        } catch (final IOException e) {
-            throw new PersistentVolumeArtifactStorageException(String.format("Could not persist artifact '%s'", filePath), e);
-        }
-
-        return new PersistentStorageArtifactInfo(filePath);
-    }
-
-    private Path buildFilePath(final String vspId, final String versionId) {
-        return buildDestinationFolder(vspId, versionId).resolve(versionId);
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return storageConfiguration != null && storageConfiguration.isEnabled();
-    }
-
-    private Optional<Path> backupPreviousVersion(final Path filePath) {
-        if (!Files.exists(filePath)) {
-            return Optional.empty();
-        }
-
-        final var backupPath = Path.of(filePath + UUID.randomUUID().toString());
-        moveFile(filePath, backupPath);
-        return Optional.ofNullable(backupPath);
-    }
-
-    private void rollback(final Path backupPath, final Path filePath) {
-        try {
-            moveFile(backupPath, filePath);
-        } catch (final Exception ex) {
-            LOGGER.warn("Could not rollback the backup file '{}' to the original '{}'", backupPath, filePath, ex);
-        }
-    }
-
-    private void removePreviousVersion(final Path filePath) {
-        if (filePath == null || !Files.exists(filePath)) {
-            return;
-        }
-
-        try {
-            Files.delete(filePath);
-        } catch (final IOException e) {
-            throw new PersistentVolumeArtifactStorageException(String.format("Could not delete previous version '%s'", filePath), e);
-        }
-    }
-
-    private Path createTempFilePath(final Path destinationFolder) {
-        final var retries = 10;
-        return createTempFilePath(destinationFolder, retries).orElseThrow(() -> {
-            throw new PersistentVolumeArtifactStorageException(String.format("Could not generate upload file path after '%s' retries", retries));
-        });
-    }
-
-    private Optional<Path> createTempFilePath(final Path destinationFolder, int retries) {
-        for (var i = 0; i < retries; i++) {
-            final var filePath = destinationFolder.resolve(UUID.randomUUID().toString());
-            if (Files.notExists(filePath)) {
-                return Optional.of(filePath);
-            }
-        }
-        return Optional.empty();
-    }
-
-    private Path buildDestinationFolder(final String vspId, final String versionId) {
-        return storageConfiguration.getStoragePath().resolve(vspId).resolve(versionId);
-    }
-
-    private void persist(final InputStream artifactInputStream, final Path filePath) throws IOException {
-        try (final var inputStream = artifactInputStream;
-            final var fileOutputStream = new FileOutputStream(filePath.toFile());) {
-            inputStream.transferTo(fileOutputStream);
-        }
-    }
-
-    private void moveFile(final Path from, final Path to) {
-        try {
-            Files.move(from, to, StandardCopyOption.REPLACE_EXISTING);
-        } catch (final IOException e) {
-            throw new PersistentVolumeArtifactStorageException(String.format("Could not move file '%s' to '%s'", from, to), e);
-        }
-    }
-
-}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/StorageFactory.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/StorageFactory.java
new file mode 100644 (file)
index 0000000..d120b3a
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.storage;
+
+import static org.openecomp.sdc.be.csar.storage.StorageFactory.StorageType.NONE;
+import static org.openecomp.sdc.be.csar.storage.StorageFactory.StorageType.findByName;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import lombok.NoArgsConstructor;
+import org.openecomp.sdc.common.CommonConfigurationManager;
+import org.openecomp.sdc.logging.api.Logger;
+import org.openecomp.sdc.logging.api.LoggerFactory;
+
+@NoArgsConstructor
+public class StorageFactory {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(StorageFactory.class);
+    private static final String EXTERNAL_CSAR_STORE = "externalCsarStore";
+
+    public ArtifactStorageManager createArtifactStorageManager() {
+        switch (getConfiguredArtifactStorageType()) {
+            case MINIO: //  MinIoStorage enabled
+                return new MinIoStorageArtifactStorageManager();
+            default://  all configured, nothing enabled
+                return new NoneStorageManager();
+        }
+    }
+
+    public Optional<PackageSizeReducer> createPackageSizeReducer() {
+        switch (getConfiguredArtifactStorageType()) {
+            case MINIO: //  MinIoStorage enabled
+                return Optional.of(new MinIoStorageCsarSizeReducer(readPackageReducerConfiguration()));
+            default://  all configured, nothing enabled
+                return Optional.empty();
+        }
+    }
+
+    private StorageType getConfiguredArtifactStorageType() {
+        final var commonConfigurationManager = CommonConfigurationManager.getInstance();
+        final String storageType = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "storageType", NONE.name());
+        LOGGER.info("ArtifactConfig.storageType: '{}'", storageType);
+        return findByName(storageType);
+    }
+
+    private CsarPackageReducerConfiguration readPackageReducerConfiguration() {
+        final var commonConfigurationManager = CommonConfigurationManager.getInstance();
+        final List<String> foldersToStrip = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "foldersToStrip", new ArrayList<>());
+        final int sizeLimit = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "sizeLimit", 1000000);
+        final int thresholdEntries = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "thresholdEntries", 10000);
+        LOGGER.info("Folders to strip: '{}'", String.join(", ", foldersToStrip));
+        final Set<Path> foldersToStripPathSet = foldersToStrip.stream().map(Path::of).collect(Collectors.toSet());
+        return new CsarPackageReducerConfiguration(foldersToStripPathSet, sizeLimit, thresholdEntries);
+    }
+
+    public enum StorageType {
+        NONE,
+        MINIO;
+
+        public static StorageType findByName(String name) {
+            for (StorageType curr : StorageType.values()) {
+                if (curr.name().equals(name)) {
+                    return curr;
+                }
+            }
+            return null;
+        }
+    }
+}
@@ -22,13 +22,13 @@ package org.openecomp.sdc.be.csar.storage.exception;
 
 import org.openecomp.sdc.be.exception.BusinessException;
 
-public class PersistentVolumeArtifactStorageException extends BusinessException {
+public class ArtifactStorageException extends BusinessException {
 
-    public PersistentVolumeArtifactStorageException(final String message, final Throwable cause) {
+    public ArtifactStorageException(final String message, final Throwable cause) {
         super(message, cause);
     }
 
-    public PersistentVolumeArtifactStorageException(final String message) {
+    public ArtifactStorageException(final String message) {
         super(message);
     }
 }
diff --git a/common-be/src/test/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageManagerTest.java b/common-be/src/test/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageManagerTest.java
new file mode 100644 (file)
index 0000000..41eed0c
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.storage;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.when;
+
+import io.minio.BucketExistsArgs;
+import io.minio.MinioClient;
+import java.io.IOException;
+import java.io.InputStream;
+import javax.activation.DataHandler;
+import org.apache.cxf.jaxrs.ext.multipart.Attachment;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.openecomp.sdc.be.csar.storage.MinIoStorageArtifactStorageConfig.Credentials;
+import org.openecomp.sdc.be.csar.storage.MinIoStorageArtifactStorageConfig.EndPoint;
+
+@ExtendWith(MockitoExtension.class)
+class MinIoStorageArtifactStorageManagerTest {
+
+    public static final String VSP_ID = "vsp-id";
+    public static final String VERSION_ID = "version-id";
+    private MinIoStorageArtifactStorageManager testSubject;
+    @Mock
+    private MinioClient minioClient;
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private MinioClient.Builder builderMinio;
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private BucketExistsArgs.Builder builderBucketExistsArgs;
+
+    @BeforeEach
+    void setUp() {
+        MockitoAnnotations.openMocks(this);
+
+        try (MockedStatic<MinioClient> utilities = Mockito.mockStatic(MinioClient.class)) {
+            utilities.when(MinioClient::builder).thenReturn(builderMinio);
+            when(builderMinio
+                .endpoint(anyString(), anyInt(), anyBoolean())
+                .credentials(anyString(), anyString())
+                .build()
+            ).thenReturn(minioClient);
+
+            testSubject = new MinIoStorageArtifactStorageManager(
+                new MinIoStorageArtifactStorageConfig(true, new EndPoint("host", 9000, false), new Credentials("accessKey", "secretKey"), ""));
+        }
+    }
+
+    @Test
+    void testUpload() throws Exception {
+
+        when(builderBucketExistsArgs
+            .bucket(anyString())
+            .build()
+        ).thenReturn(new BucketExistsArgs());
+        when(minioClient.bucketExists(any(BucketExistsArgs.class))).thenReturn(true);
+
+        final Attachment attachment = mockAttachment();
+        final ArtifactInfo result = testSubject.upload(VSP_ID, VERSION_ID, attachment.getDataHandler().getInputStream());
+        Assertions.assertNotNull(result);
+        Assertions.assertTrue(result instanceof MinIoArtifactInfo);
+        Assertions.assertEquals(VSP_ID, ((MinIoArtifactInfo) result).getBucket());
+        Assertions.assertTrue(((MinIoArtifactInfo) result).getObjectName().startsWith(VERSION_ID + "--"));
+    }
+
+    @Test
+    void testPersist() {
+        final ArtifactInfo result = testSubject.persist(VSP_ID, VERSION_ID, new MinIoArtifactInfo(VSP_ID, VERSION_ID));
+        Assertions.assertNotNull(result);
+        Assertions.assertTrue(result instanceof MinIoArtifactInfo);
+        Assertions.assertEquals(VSP_ID, ((MinIoArtifactInfo) result).getBucket());
+        Assertions.assertEquals(VERSION_ID, ((MinIoArtifactInfo) result).getObjectName());
+    }
+
+    @Test
+    void testIsEnabled() {
+        Assertions.assertTrue(testSubject.isEnabled());
+    }
+
+    private Attachment mockAttachment() throws IOException {
+        final Attachment attachment = Mockito.mock(Attachment.class);
+        final DataHandler dataHandler = Mockito.mock(DataHandler.class);
+        final InputStream inputStream = Mockito.mock(InputStream.class);
+        when(dataHandler.getInputStream()).thenReturn(inputStream);
+        when(attachment.getDataHandler()).thenReturn(dataHandler);
+        return attachment;
+    }
+
+}
@@ -42,12 +42,12 @@ import org.mockito.MockitoAnnotations;
 import org.openecomp.sdc.common.zip.ZipUtils;
 import org.openecomp.sdc.common.zip.exception.ZipException;
 
-class CsarSizeReducerTest {
+class MinIoStorageCsarSizeReducerTest {
 
     @Mock
     private CsarPackageReducerConfiguration csarPackageReducerConfiguration;
     @InjectMocks
-    private CsarSizeReducer csarSizeReducer;
+    private MinIoStorageCsarSizeReducer minIoStorageCsarSizeReducer;
 
     @BeforeEach
     void setUp() {
@@ -55,7 +55,7 @@ class CsarSizeReducerTest {
     }
 
     @ParameterizedTest
-    @ValueSource(strings = {"dummyToReduce.zip", "dummyToReduce.csar", "dummyToNotReduce.csar"})
+    @ValueSource(strings = {"dummyToReduce-3-files.zip", "dummyToReduce.csar", "dummyToNotReduce.csar", "dummyToReduce-2-files.zip"})
     void reduceByPathAndSizeTest(String fileName) throws ZipException {
         final var pathToReduce1 = Path.of("Files/images");
         final var pathToReduce2 = Path.of("Files/Scripts/my_script.sh");
@@ -68,7 +68,7 @@ class CsarSizeReducerTest {
 
         final Map<String, byte[]> originalCsar = ZipUtils.readZip(csarPath.toFile(), false);
 
-        final byte[] reduce = csarSizeReducer.reduce(csarPath);
+        final byte[] reduce = minIoStorageCsarSizeReducer.reduce(csarPath);
 
         final Map<String, byte[]> reducedCsar = ZipUtils.readZip(reduce, false);
 
@@ -113,7 +113,7 @@ class CsarSizeReducerTest {
             assertArrayEquals("".getBytes(StandardCharsets.UTF_8), reducedCsar.get(originalFilePath),
                 String.format("File '%s' expected to be reduced to empty string", originalFilePath));
         } else {
-            if (originalFilePath.endsWith(".csar") && csarSizeReducer.getReduced().get()) {
+            if (originalFilePath.endsWith(".csar") && minIoStorageCsarSizeReducer.getReduced().get()) {
                 assertNotEquals(originalBytes.length, reducedCsar.get(originalFilePath).length,
                     String.format("File '%s' expected to be NOT equal", originalFilePath));
             } else {
@@ -122,4 +122,4 @@ class CsarSizeReducerTest {
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/common-be/src/test/java/org/openecomp/sdc/be/csar/storage/NoneStorageManagerTest.java b/common-be/src/test/java/org/openecomp/sdc/be/csar/storage/NoneStorageManagerTest.java
new file mode 100644 (file)
index 0000000..58394b9
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.csar.storage;
+
+import java.io.ByteArrayInputStream;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+class NoneStorageManagerTest {
+
+    public static final MinIoArtifactInfo UPLOADED_ARTIFACT_INFO = new MinIoArtifactInfo("bucket", "object");
+    private NoneStorageManager testSubject;
+
+    @BeforeEach
+    void setUp() {
+        testSubject = new NoneStorageManager();
+    }
+
+    @Test
+    void testCtor() {
+        Assertions.assertTrue(testSubject instanceof NoneStorageManager);
+    }
+
+    @Test
+    void testPersist() {
+        Assertions.assertThrows(UnsupportedOperationException.class,
+            () -> testSubject.persist("vspId", "versionId", UPLOADED_ARTIFACT_INFO));
+    }
+
+    @Test
+    void testUpload() {
+        Assertions.assertThrows(UnsupportedOperationException.class,
+            () -> testSubject.upload("vspId", "versionId", new ByteArrayInputStream(new byte[0])));
+    }
+
+    @Test
+    void testGetStorageConfiguration() {
+        Assertions.assertThrows(UnsupportedOperationException.class, () -> testSubject.getStorageConfiguration());
+    }
+
+    @Test
+    void testGet() {
+        Assertions.assertThrows(UnsupportedOperationException.class, () -> testSubject.get(UPLOADED_ARTIFACT_INFO));
+    }
+
+    @Test
+    void testDelete() {
+        Assertions.assertThrows(UnsupportedOperationException.class, () -> testSubject.delete(UPLOADED_ARTIFACT_INFO));
+    }
+
+    @Test
+    void testIsEnabled() {
+        Assertions.assertFalse(testSubject.isEnabled());
+    }
+
+}
diff --git a/common-be/src/test/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageManagerTest.java b/common-be/src/test/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageManagerTest.java
deleted file mode 100644 (file)
index ab8c11c..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
- *  ================================================================================
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  SPDX-License-Identifier: Apache-2.0
- *  ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.be.csar.storage;
-
-import static org.junit.jupiter.api.Assertions.fail;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Objects;
-import javax.activation.DataHandler;
-import org.apache.commons.io.IOUtils;
-import org.apache.cxf.jaxrs.ext.multipart.Attachment;
-import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
-import org.junit.jupiter.api.Order;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestMethodOrder;
-import org.mockito.ArgumentMatchers;
-import org.mockito.Mockito;
-
-@TestMethodOrder(OrderAnnotation.class)
-class PersistentVolumeArtifactStorageManagerTest {
-
-    private static final String SRC_TEST_RESOURCES = "src/test/resources/";
-
-    private PersistentVolumeArtifactStorageManager testSubject;
-
-    @BeforeEach
-    void setUp() {
-        testSubject = new PersistentVolumeArtifactStorageManager(new PersistentVolumeArtifactStorageConfig(true, Path.of(SRC_TEST_RESOURCES)));
-    }
-
-    @AfterAll
-    static void tearDown() throws IOException {
-        Files.move(Path.of(SRC_TEST_RESOURCES + "vspId/versionId/versionId"),
-            Path.of(SRC_TEST_RESOURCES + "persistentVolumeArtifactStorageManager/dummy.csar"));
-        Files.list(Path.of("src/test/resources/vspId/versionId/")).forEach(path -> {
-            try {
-                Files.deleteIfExists(path);
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        });
-        Files.deleteIfExists(Path.of(SRC_TEST_RESOURCES + "vspId/versionId/"));
-        Files.deleteIfExists(Path.of(SRC_TEST_RESOURCES + "vspId/"));
-    }
-
-    @Test
-    @Order(1)
-    void testUpload() throws IOException {
-        final Attachment attachment = mockAttachment("dummy.csar", this.getClass().getResource("/persistentVolumeArtifactStorageManager/dummy.csar"));
-        final ArtifactInfo result = testSubject.upload("vspId", "versionId", attachment.getDataHandler().getInputStream());
-        Assertions.assertNotNull(result);
-        Assertions.assertNotNull(result.getPath());
-        Assertions.assertTrue(result.getPath().startsWith(Path.of(SRC_TEST_RESOURCES + "vspId/versionId/")));
-    }
-
-    @Test
-    @Order(2)
-    void testPersist() {
-        final ArtifactInfo result = testSubject.persist("vspId", "versionId",
-            new PersistentStorageArtifactInfo(Path.of(SRC_TEST_RESOURCES + "persistentVolumeArtifactStorageManager/dummy.csar")));
-        Assertions.assertNotNull(result);
-        Assertions.assertNotNull(result.getPath());
-        Assertions.assertTrue(result.getPath().startsWith(Path.of(SRC_TEST_RESOURCES + "vspId/versionId/")));
-    }
-
-    @Test
-    void testIsEnabled() {
-        Assertions.assertTrue(testSubject.isEnabled());
-    }
-
-    private Attachment mockAttachment(final String fileName, final URL fileToUpload) throws IOException {
-        final Attachment attachment = Mockito.mock(Attachment.class);
-        when(attachment.getContentDisposition()).thenReturn(new ContentDisposition("test"));
-        final DataHandler dataHandler = Mockito.mock(DataHandler.class);
-        when(dataHandler.getName()).thenReturn(fileName);
-        final InputStream inputStream = Mockito.mock(InputStream.class);
-        when(dataHandler.getInputStream()).thenReturn(inputStream);
-        when(attachment.getDataHandler()).thenReturn(dataHandler);
-        byte[] bytes = "upload package Test".getBytes();
-        if (Objects.nonNull(fileToUpload)) {
-            try {
-                bytes = IOUtils.toByteArray(fileToUpload);
-            } catch (final IOException e) {
-                fail("Not able to convert file to byte array");
-            }
-        }
-        when(attachment.getObject(ArgumentMatchers.any())).thenReturn(bytes);
-        return attachment;
-    }
-
-}
diff --git a/common-be/src/test/resources/csarSizeReducer/dummyToReduce-2-files.zip b/common-be/src/test/resources/csarSizeReducer/dummyToReduce-2-files.zip
new file mode 100644 (file)
index 0000000..be48e8a
Binary files /dev/null and b/common-be/src/test/resources/csarSizeReducer/dummyToReduce-2-files.zip differ
diff --git a/common-be/src/test/resources/s3StoreArtifactStorageManager/dummy.csar b/common-be/src/test/resources/s3StoreArtifactStorageManager/dummy.csar
new file mode 100644 (file)
index 0000000..73b28f5
Binary files /dev/null and b/common-be/src/test/resources/s3StoreArtifactStorageManager/dummy.csar differ
index 23930ed..6fe7f9d 100644 (file)
@@ -28,13 +28,14 @@ import static javax.ws.rs.core.Response.Status.NOT_FOUND;
 import static org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder.getErrorWithParameters;
 import static org.openecomp.sdc.common.errors.Messages.ERROR_HAS_OCCURRED_WHILE_PERSISTING_THE_ARTIFACT;
 import static org.openecomp.sdc.common.errors.Messages.ERROR_HAS_OCCURRED_WHILE_REDUCING_THE_ARTIFACT_SIZE;
-import static org.openecomp.sdc.common.errors.Messages.EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING_FULL_PATH;
 import static org.openecomp.sdc.common.errors.Messages.NO_FILE_WAS_UPLOADED_OR_FILE_NOT_EXIST;
 import static org.openecomp.sdc.common.errors.Messages.PACKAGE_PROCESS_ERROR;
 import static org.openecomp.sdc.common.errors.Messages.UNEXPECTED_PROBLEM_HAPPENED_WHILE_GETTING;
 
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -42,8 +43,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
+import java.util.UUID;
+import javax.activation.DataHandler;
 import javax.inject.Named;
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.tuple.Pair;
@@ -55,13 +56,8 @@ import org.openecomp.sdc.activitylog.dao.type.ActivityType;
 import org.openecomp.sdc.be.csar.storage.ArtifactInfo;
 import org.openecomp.sdc.be.csar.storage.ArtifactStorageConfig;
 import org.openecomp.sdc.be.csar.storage.ArtifactStorageManager;
-import org.openecomp.sdc.be.csar.storage.CsarPackageReducerConfiguration;
-import org.openecomp.sdc.be.csar.storage.CsarSizeReducer;
 import org.openecomp.sdc.be.csar.storage.PackageSizeReducer;
-import org.openecomp.sdc.be.csar.storage.PersistentVolumeArtifactStorageConfig;
-import org.openecomp.sdc.be.csar.storage.PersistentVolumeArtifactStorageManager;
-import org.openecomp.sdc.be.exception.BusinessException;
-import org.openecomp.sdc.common.CommonConfigurationManager;
+import org.openecomp.sdc.be.csar.storage.StorageFactory;
 import org.openecomp.sdc.common.util.ValidationUtils;
 import org.openecomp.sdc.common.utils.SdcCommon;
 import org.openecomp.sdc.datatypes.error.ErrorLevel;
@@ -98,7 +94,6 @@ import org.springframework.stereotype.Service;
 public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplateCandidate {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(OrchestrationTemplateCandidateImpl.class);
-    private static final String EXTERNAL_CSAR_STORE = "externalCsarStore";
     private final OrchestrationTemplateCandidateManager candidateManager;
     private final VendorSoftwareProductManager vendorSoftwareProductManager;
     private final ActivityLogManager activityLogManager;
@@ -110,9 +105,10 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate
         this.vendorSoftwareProductManager = VspManagerFactory.getInstance().createInterface();
         this.activityLogManager = ActivityLogManagerFactory.getInstance().createInterface();
         LOGGER.info("Instantiating artifactStorageManager");
-        this.artifactStorageManager = new PersistentVolumeArtifactStorageManager(readArtifactStorageConfiguration());
+        final StorageFactory storageFactory = new StorageFactory();
+        this.artifactStorageManager = storageFactory.createArtifactStorageManager();
         LOGGER.info("Instantiating packageSizeReducer");
-        this.packageSizeReducer = new CsarSizeReducer(readPackageReducerConfiguration());
+        this.packageSizeReducer = storageFactory.createPackageSizeReducer().orElse(null);
     }
 
     // Constructor used in test to avoid mock static
@@ -128,56 +124,45 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate
         this.packageSizeReducer = packageSizeReducer;
     }
 
-    private CsarPackageReducerConfiguration readPackageReducerConfiguration() {
-        final var commonConfigurationManager = CommonConfigurationManager.getInstance();
-        final List<String> foldersToStrip = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "foldersToStrip", new ArrayList<>());
-        final int sizeLimit = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "sizeLimit", 1000000);
-        final int thresholdEntries = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "thresholdEntries", 10000);
-        LOGGER.info("Folders to strip: '{}'", String.join(", ", foldersToStrip));
-        final Set<Path> foldersToStripPathSet = foldersToStrip.stream().map(Path::of).collect(Collectors.toSet());
-        return new CsarPackageReducerConfiguration(foldersToStripPathSet, sizeLimit, thresholdEntries);
-    }
-
-    private ArtifactStorageConfig readArtifactStorageConfiguration() {
-        final var commonConfigurationManager = CommonConfigurationManager.getInstance();
-        final boolean isEnabled = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "storeCsarsExternally", false);
-        LOGGER.info("ArtifactConfig.isEnabled: '{}'", isEnabled);
-        final String storagePathString = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "fullPath", null);
-        LOGGER.info("ArtifactConfig.storagePath: '{}'", storagePathString);
-        if (isEnabled && storagePathString == null) {
-            throw new OrchestrationTemplateCandidateException(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING_FULL_PATH.getErrorMessage());
-        }
-        final var storagePath = storagePathString == null ? null : Path.of(storagePathString);
-        return new PersistentVolumeArtifactStorageConfig(isEnabled, storagePath);
-    }
-
     @Override
     public Response upload(String vspId, String versionId, final Attachment fileToUpload, final String user) {
         vspId = ValidationUtils.sanitizeInputString(vspId);
         versionId = ValidationUtils.sanitizeInputString(versionId);
         final byte[] fileToUploadBytes;
-        final var filename = ValidationUtils.sanitizeInputString(fileToUpload.getDataHandler().getName());
+        final DataHandler dataHandler = fileToUpload.getDataHandler();
+        final var filename = ValidationUtils.sanitizeInputString(dataHandler.getName());
         ArtifactInfo artifactInfo = null;
         if (artifactStorageManager.isEnabled()) {
-            final InputStream packageInputStream;
+            final Path tempArtifactPath;
             try {
-                packageInputStream = fileToUpload.getDataHandler().getInputStream();
-            } catch (final IOException e) {
+                final ArtifactStorageConfig storageConfiguration = artifactStorageManager.getStorageConfiguration();
+
+                final Path folder = Path.of(storageConfiguration.getTempPath()).resolve(vspId).resolve(versionId);
+                tempArtifactPath = folder.resolve(UUID.randomUUID().toString());
+                Files.createDirectories(folder);
+                try (final InputStream packageInputStream = dataHandler.getInputStream();
+                    final var fileOutputStream = new FileOutputStream(tempArtifactPath.toFile())) {
+                    packageInputStream.transferTo(fileOutputStream);
+                }
+            } catch (final Exception e) {
                 return Response.status(INTERNAL_SERVER_ERROR).entity(buildUploadResponseWithError(
                     new ErrorMessage(ErrorLevel.ERROR, UNEXPECTED_PROBLEM_HAPPENED_WHILE_GETTING.formatMessage(filename)))).build();
             }
-            try {
-                artifactInfo = artifactStorageManager.upload(vspId, versionId, packageInputStream);
-            } catch (final BusinessException e) {
+            try (final InputStream inputStream = Files.newInputStream(tempArtifactPath)) {
+                artifactInfo = artifactStorageManager.upload(vspId, versionId, inputStream);
+            } catch (final Exception e) {
+                LOGGER.error("Package Size Reducer not configured", e);
                 return Response.status(INTERNAL_SERVER_ERROR).entity(buildUploadResponseWithError(
                     new ErrorMessage(ErrorLevel.ERROR, ERROR_HAS_OCCURRED_WHILE_PERSISTING_THE_ARTIFACT.formatMessage(filename)))).build();
             }
             try {
-                fileToUploadBytes = packageSizeReducer.reduce(artifactInfo.getPath());
-            } catch (final BusinessException e) {
+                fileToUploadBytes = packageSizeReducer.reduce(tempArtifactPath);
+                Files.delete(tempArtifactPath);
+            } catch (final Exception e) {
+                LOGGER.error("Package Size Reducer not configured", e);
                 return Response.status(INTERNAL_SERVER_ERROR).entity(buildUploadResponseWithError(
-                        new ErrorMessage(ErrorLevel.ERROR, ERROR_HAS_OCCURRED_WHILE_REDUCING_THE_ARTIFACT_SIZE.formatMessage(artifactInfo.getPath()))))
-                    .build();
+                    new ErrorMessage(ErrorLevel.ERROR,
+                        ERROR_HAS_OCCURRED_WHILE_REDUCING_THE_ARTIFACT_SIZE.formatMessage(tempArtifactPath.toString())))).build();
             }
         } else {
             fileToUploadBytes = fileToUpload.getObject(byte[].class);
@@ -192,12 +177,16 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate
         if (onboardPackageInfo == null) {
             final UploadFileResponseDto uploadFileResponseDto = buildUploadResponseWithError(
                 new ErrorMessage(ErrorLevel.ERROR, PACKAGE_PROCESS_ERROR.formatMessage(filename)));
-            return Response.ok(uploadFileResponseDto)
-                .build();
+            return Response.ok(uploadFileResponseDto).build();
         }
         final var version = new Version(versionId);
         final var vspDetails = vendorSoftwareProductManager.getVsp(vspId, version);
-        return processOnboardPackage(onboardPackageInfo, vspDetails, errorMessages);
+        final Response response = processOnboardPackage(onboardPackageInfo, vspDetails, errorMessages);
+        final UploadFileResponseDto entity = (UploadFileResponseDto) response.getEntity();
+        if (artifactStorageManager.isEnabled() && !entity.getErrors().isEmpty()) {
+            artifactStorageManager.delete(artifactInfo);
+        }
+        return response;
     }
 
     private Response processOnboardPackage(final OnboardPackageInfo onboardPackageInfo, final VspDetails vspDetails,
index edf29b7..2d2c308 100644 (file)
@@ -32,6 +32,8 @@ import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.when;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.URL;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -49,14 +51,18 @@ import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentMatchers;
+import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
 import org.openecomp.sdc.activitylog.ActivityLogManager;
 import org.openecomp.sdc.be.csar.storage.ArtifactStorageManager;
+import org.openecomp.sdc.be.csar.storage.MinIoArtifactInfo;
+import org.openecomp.sdc.be.csar.storage.MinIoStorageArtifactStorageConfig;
+import org.openecomp.sdc.be.csar.storage.MinIoStorageArtifactStorageConfig.Credentials;
+import org.openecomp.sdc.be.csar.storage.MinIoStorageArtifactStorageConfig.EndPoint;
 import org.openecomp.sdc.be.csar.storage.PackageSizeReducer;
-import org.openecomp.sdc.be.csar.storage.PersistentStorageArtifactInfo;
 import org.openecomp.sdc.logging.api.Logger;
 import org.openecomp.sdc.logging.api.LoggerFactory;
 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager;
@@ -88,6 +94,7 @@ class OrchestrationTemplateCandidateImplTest {
     private ArtifactStorageManager artifactStorageManager;
     @Mock
     private PackageSizeReducer packageSizeReducer;
+    @InjectMocks
     private OrchestrationTemplateCandidateImpl orchestrationTemplateCandidate;
 
     @BeforeEach
@@ -132,20 +139,15 @@ class OrchestrationTemplateCandidateImplTest {
                 ArgumentMatchers.eq(candidateId),
                 ArgumentMatchers.any())).thenReturn(Optional.of(fds));
 
-            orchestrationTemplateCandidate =
-                new OrchestrationTemplateCandidateImpl(candidateManager, vendorSoftwareProductManager, activityLogManager,
-                    artifactStorageManager, packageSizeReducer);
-
         } catch (Exception e) {
             logger.error(e.getMessage(), e);
         }
     }
 
     @Test
-    void uploadSignedTest() {
+    void uploadSignedTest() throws IOException {
         Response response = orchestrationTemplateCandidate
-            .upload("1", "1", mockAttachment("filename.zip", this.getClass().getResource("/files/sample-signed.zip")),
-                "1");
+            .upload("1", "1", mockAttachment("filename.zip", this.getClass().getResource("/files/sample-signed.zip")), user);
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
         assertTrue(((UploadFileResponseDto) response.getEntity()).getErrors().isEmpty());
     }
@@ -153,7 +155,7 @@ class OrchestrationTemplateCandidateImplTest {
     @Test
     void uploadNotSignedTest() throws IOException {
         Response response = orchestrationTemplateCandidate.upload("1", "1",
-            mockAttachment("filename.csar", this.getClass().getResource("/files/sample-not-signed.csar")), "1");
+            mockAttachment("filename.csar", this.getClass().getResource("/files/sample-not-signed.csar")), user);
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
         assertTrue(((UploadFileResponseDto) response.getEntity()).getErrors().isEmpty());
     }
@@ -161,23 +163,29 @@ class OrchestrationTemplateCandidateImplTest {
     @Test
     void uploadNotSignedArtifactStorageManagerIsEnabledTest() throws IOException {
         when(artifactStorageManager.isEnabled()).thenReturn(true);
+        when(artifactStorageManager.getStorageConfiguration()).thenReturn(
+            new MinIoStorageArtifactStorageConfig(true, new EndPoint("host", 9000, false), new Credentials("accessKey", "secretKey"), "tempPath"));
+
         final Path path = Path.of("src/test/resources/files/sample-not-signed.csar");
-        when(artifactStorageManager.upload(anyString(), anyString(), any())).thenReturn(new PersistentStorageArtifactInfo(path));
+        when(artifactStorageManager.upload(anyString(), anyString(), any())).thenReturn(new MinIoArtifactInfo("vspId", "name"));
         final byte[] bytes = Files.readAllBytes(path);
         when(packageSizeReducer.reduce(any())).thenReturn(bytes);
 
         Response response = orchestrationTemplateCandidate.upload("1", "1",
-            mockAttachment("filename.csar", this.getClass().getResource("/files/sample-not-signed.csar")), "1");
+            mockAttachment("filename.csar", this.getClass().getResource("/files/sample-not-signed.csar")), user);
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
         assertTrue(((UploadFileResponseDto) response.getEntity()).getErrors().isEmpty());
     }
 
-    private Attachment mockAttachment(final String fileName, final URL fileToUpload) {
+    private Attachment mockAttachment(final String fileName, final URL fileToUpload) throws IOException {
         final Attachment attachment = Mockito.mock(Attachment.class);
+        final InputStream inputStream = Mockito.mock(InputStream.class);
         when(attachment.getContentDisposition()).thenReturn(new ContentDisposition("test"));
         final DataHandler dataHandler = Mockito.mock(DataHandler.class);
         when(dataHandler.getName()).thenReturn(fileName);
         when(attachment.getDataHandler()).thenReturn(dataHandler);
+        when(dataHandler.getInputStream()).thenReturn(inputStream);
+        when(inputStream.transferTo(any(OutputStream.class))).thenReturn(0L);
         byte[] bytes = "upload package Test".getBytes();
         if (Objects.nonNull(fileToUpload)) {
             try {
@@ -192,9 +200,9 @@ class OrchestrationTemplateCandidateImplTest {
     }
 
     @Test
-    void uploadSignNotValidTest() {
+    void uploadSignNotValidTest() throws IOException {
         Response response = orchestrationTemplateCandidate
-            .upload("1", "1", mockAttachment("filename.zip", null), "1");
+            .upload("1", "1", mockAttachment("filename.zip", null), user);
         assertEquals(Status.NOT_ACCEPTABLE.getStatusCode(), response.getStatus());
         assertFalse(((UploadFileResponseDto) response.getEntity()).getErrors().isEmpty());
     }
index fec15b5..53728c0 100644 (file)
  */
 package org.openecomp.sdc.vendorsoftwareproduct.security;
 
-import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
-
 import com.google.common.collect.ImmutableSet;
+import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -56,7 +56,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import java.util.zip.ZipFile;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
 import org.bouncycastle.asn1.cms.ContentInfo;
 import org.bouncycastle.cert.X509CertificateHolder;
 import org.bouncycastle.cms.CMSException;
@@ -69,7 +70,9 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.openssl.PEMParser;
 import org.bouncycastle.operator.OperatorCreationException;
 import org.openecomp.sdc.be.csar.storage.ArtifactInfo;
-import org.openecomp.sdc.common.errors.SdcRuntimeException;
+import org.openecomp.sdc.be.csar.storage.ArtifactStorageConfig;
+import org.openecomp.sdc.be.csar.storage.ArtifactStorageManager;
+import org.openecomp.sdc.be.csar.storage.StorageFactory;
 import org.openecomp.sdc.logging.api.Logger;
 import org.openecomp.sdc.logging.api.LoggerFactory;
 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardSignedPackage;
@@ -83,9 +86,10 @@ public class SecurityManager {
     public static final Set<String> ALLOWED_SIGNATURE_EXTENSIONS = Set.of("cms");
     public static final Set<String> ALLOWED_CERTIFICATE_EXTENSIONS = Set.of("cert", "crt");
     private static final String CERTIFICATE_DEFAULT_LOCATION = "cert";
-    private static final Logger logger = LoggerFactory.getLogger(SecurityManager.class);
+    private static final Logger LOGGER = LoggerFactory.getLogger(SecurityManager.class);
     private static final String UNEXPECTED_ERROR_OCCURRED_DURING_SIGNATURE_VALIDATION = "Unexpected error occurred during signature validation!";
     private static final String COULD_NOT_VERIFY_SIGNATURE = "Could not verify signature!";
+    private static final String EXTERNAL_CSAR_STORE = "externalCsarStore";
 
     static {
         if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
@@ -120,7 +124,7 @@ public class SecurityManager {
         //if file number in certificate directory changed reload certs
         String[] certFiles = certificateDirectory.list();
         if (certFiles == null) {
-            logger.error("Certificate directory is empty!");
+            LOGGER.error("Certificate directory is empty!");
             return ImmutableSet.copyOf(new HashSet<>());
         }
         if (trustedCertificates.size() != certFiles.length) {
@@ -160,7 +164,7 @@ public class SecurityManager {
             }
             return verify(packageCert, new CMSSignedData(new CMSProcessableByteArray(innerPackageFile), ContentInfo.getInstance(parsedObject)));
         } catch (final IOException | CMSException e) {
-            logger.error(e.getMessage(), e);
+            LOGGER.error(e.getMessage(), e);
             throw new SecurityManagerException(UNEXPECTED_ERROR_OCCURRED_DURING_SIGNATURE_VALIDATION, e);
         }
     }
@@ -168,14 +172,27 @@ public class SecurityManager {
     public boolean verifyPackageSignedData(final OnboardSignedPackage signedPackage, final ArtifactInfo artifactInfo)
         throws SecurityManagerException {
         boolean fail = false;
+
+        final StorageFactory storageFactory = new StorageFactory();
+        final ArtifactStorageManager artifactStorageManager = storageFactory.createArtifactStorageManager();
+        final ArtifactStorageConfig storageConfiguration = artifactStorageManager.getStorageConfiguration();
+
         final var fileContentHandler = signedPackage.getFileContentHandler();
         byte[] packageCert = null;
         final Optional<String> certificateFilePath = signedPackage.getCertificateFilePath();
         if (certificateFilePath.isPresent()) {
             packageCert = fileContentHandler.getFileContent(certificateFilePath.get());
         }
-        final var path = artifactInfo.getPath();
-        final var target = Path.of(path.toString() + "." + UUID.randomUUID());
+
+        final Path folder = Path.of(storageConfiguration.getTempPath());
+        try {
+            Files.createDirectories(folder);
+        } catch (final IOException e) {
+            fail = true;
+            throw new SecurityManagerException(String.format("Failed to create directory '%s'", folder), e);
+        }
+
+        final var target = folder.resolve(UUID.randomUUID().toString());
 
         try (final var signatureStream = new ByteArrayInputStream(fileContentHandler.getFileContent(signedPackage.getSignatureFilePath()));
             final var pemParser = new PEMParser(new InputStreamReader(signatureStream))) {
@@ -185,16 +202,18 @@ public class SecurityManager {
                 throw new SecurityManagerException("Signature is not recognized");
             }
 
-            if (!findCSARandExtract(path, target)) {
-                fail = true;
-                return false;
+            try (final InputStream inputStream = artifactStorageManager.get(artifactInfo)) {
+                if (!findCSARandExtract(inputStream, target)) {
+                    fail = true;
+                    return false;
+                }
             }
             final var verify = verify(packageCert, new CMSSignedData(new CMSProcessableFile(target.toFile()), ContentInfo.getInstance(parsedObject)));
             fail = !verify;
             return verify;
         } catch (final IOException e) {
             fail = true;
-            logger.error(e.getMessage(), e);
+            LOGGER.error(e.getMessage(), e);
             throw new SecurityManagerException(UNEXPECTED_ERROR_OCCURRED_DURING_SIGNATURE_VALIDATION, e);
         } catch (final CMSException e) {
             fail = true;
@@ -205,7 +224,7 @@ public class SecurityManager {
         } finally {
             deleteFile(target);
             if (fail) {
-                deleteFile(path);
+                artifactStorageManager.delete(artifactInfo);
             }
         }
     }
@@ -214,7 +233,7 @@ public class SecurityManager {
         try {
             Files.delete(filePath);
         } catch (final IOException e) {
-            logger.warn("Failed to delete '{}' after verifying package signed data", filePath, e);
+            LOGGER.warn("Failed to delete '{}' after verifying package signed data", filePath, e);
         }
     }
 
@@ -246,20 +265,25 @@ public class SecurityManager {
         }
     }
 
-    private boolean findCSARandExtract(final Path path, final Path target) throws IOException {
+    private boolean findCSARandExtract(final InputStream inputStream, final Path target) throws IOException {
         final AtomicBoolean found = new AtomicBoolean(false);
-        try (final var zf = new ZipFile(path.toString())) {
-            zf.entries().asIterator().forEachRemaining(entry -> {
-                final var entryName = entry.getName();
-                if (!entry.isDirectory() && entryName.toLowerCase().endsWith(".csar")) {
-                    try {
-                        Files.copy(zf.getInputStream(entry), target, REPLACE_EXISTING);
-                    } catch (final IOException e) {
-                        throw new SdcRuntimeException(UNEXPECTED_ERROR_OCCURRED_DURING_SIGNATURE_VALIDATION, e);
+
+        final var zipInputStream = new ZipInputStream(inputStream);
+        ZipEntry zipEntry;
+        byte[] buffer = new byte[2048];
+        while ((zipEntry = zipInputStream.getNextEntry()) != null) {
+            final var entryName = zipEntry.getName();
+            if (!zipEntry.isDirectory() && entryName.toLowerCase().endsWith(".csar")) {
+                try (final FileOutputStream fos = new FileOutputStream(target.toFile());
+                    final BufferedOutputStream bos = new BufferedOutputStream(fos, buffer.length)) {
+
+                    int len;
+                    while ((len = zipInputStream.read(buffer)) > 0) {
+                        bos.write(buffer, 0, len);
                     }
-                    found.set(true);
                 }
-            });
+                found.set(true);
+            }
         }
         return found.get();
     }
@@ -289,12 +313,12 @@ public class SecurityManager {
 
     private void processCertificateDir() throws SecurityManagerException {
         if (!certificateDirectory.exists() || !certificateDirectory.isDirectory()) {
-            logger.error("Issue with certificate directory, check if exists!");
+            LOGGER.error("Issue with certificate directory, check if exists!");
             return;
         }
         File[] files = certificateDirectory.listFiles();
         if (files == null) {
-            logger.error("Certificate directory is empty!");
+            LOGGER.error("Certificate directory is empty!");
             return;
         }
         for (File f : files) {
@@ -399,10 +423,10 @@ public class SecurityManager {
         try {
             cert.checkValidity();
         } catch (CertificateExpiredException e) {
-            logger.error(e.getMessage(), e);
+            LOGGER.error(e.getMessage(), e);
             return true;
         } catch (CertificateNotYetValidException e) {
-            logger.error(e.getMessage(), e);
+            LOGGER.error(e.getMessage(), e);
             return false;
         }
         return false;
index 96d11eb..5f88070 100644 (file)
@@ -24,25 +24,43 @@ import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.when;
-import static org.mockito.MockitoAnnotations.initMocks;
-
+import static org.mockito.MockitoAnnotations.openMocks;
+import static org.openecomp.sdc.be.csar.storage.StorageFactory.StorageType.MINIO;
+
+import io.minio.GetObjectArgs;
+import io.minio.GetObjectResponse;
+import io.minio.MinioClient;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 import java.util.stream.Collectors;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Answers;
 import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
 import org.openecomp.sdc.be.csar.storage.ArtifactInfo;
-import org.openecomp.sdc.be.csar.storage.PersistentStorageArtifactInfo;
+import org.openecomp.sdc.be.csar.storage.MinIoArtifactInfo;
+import org.openecomp.sdc.common.CommonConfigurationManager;
 import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.OnboardingPackageProcessor;
 import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.validation.CnfPackageValidator;
 import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManager;
@@ -50,6 +68,7 @@ import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManagerException
 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo;
 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardSignedPackage;
 
+@ExtendWith(MockitoExtension.class)
 class CsarSecurityValidatorTest {
 
     private static final String BASE_DIR = "/vspmanager.csar/signing/";
@@ -57,6 +76,16 @@ class CsarSecurityValidatorTest {
     private CsarSecurityValidator csarSecurityValidator;
     @Mock
     private SecurityManager securityManager;
+    @Mock
+    private CommonConfigurationManager commonConfigurationManager;
+    @Mock
+    private MinioClient minioClient;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private MinioClient.Builder builderMinio;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private GetObjectArgs.Builder getObjectArgsBuilder;
+    @Mock
+    private GetObjectArgs getObjectArgs;
 
     @AfterEach
     void tearDown() throws Exception {
@@ -74,7 +103,7 @@ class CsarSecurityValidatorTest {
 
     @BeforeEach
     public void setUp() throws Exception {
-        initMocks(this);
+        openMocks(this);
         csarSecurityValidator = new CsarSecurityValidator(securityManager);
         backup();
     }
@@ -88,9 +117,9 @@ class CsarSecurityValidatorTest {
     }
 
     @Test
-    void isSignatureValidTestCorrectStructureAndValidSignatureExists() throws SecurityManagerException, IOException {
+    void isSignatureValidTestCorrectStructureAndValidSignatureExists() throws SecurityManagerException {
         final byte[] packageBytes = getFileBytesOrFail("signed-package.zip");
-        final OnboardPackageInfo onboardPackageInfo = loadSignedPackageWithArtifactInfo("signed-package.zip", packageBytes, null);
+        final OnboardPackageInfo onboardPackageInfo = loadSignedPackageWithArtifactInfoS3Store("signed-package.zip", packageBytes, null);
         when(securityManager.verifyPackageSignedData(any(OnboardSignedPackage.class), any(ArtifactInfo.class))).thenReturn(true);
         final boolean isSignatureValid = csarSecurityValidator
             .verifyPackageSignature((OnboardSignedPackage) onboardPackageInfo.getOriginalOnboardPackage(), onboardPackageInfo.getArtifactInfo());
@@ -98,15 +127,53 @@ class CsarSecurityValidatorTest {
     }
 
     @Test
-    void isSignatureValidTestCorrectStructureAndNotValidSignatureExists() throws SecurityManagerException {
-        final byte[] packageBytes = getFileBytesOrFail("signed-package-tampered-data.zip");
-        final OnboardPackageInfo onboardPackageInfo = loadSignedPackageWithArtifactInfo("signed-package-tampered-data.zip", packageBytes, null);
-        //no mocked securityManager
-        csarSecurityValidator = new CsarSecurityValidator();
-        Assertions.assertThrows(SecurityManagerException.class, () -> {
-            csarSecurityValidator
-                .verifyPackageSignature((OnboardSignedPackage) onboardPackageInfo.getOriginalOnboardPackage(), onboardPackageInfo.getArtifactInfo());
-        });
+    void isSignatureValidTestCorrectStructureAndNotValidSignatureExists() throws Exception {
+
+        final Map<String, Object> endpoint = new HashMap<>();
+        endpoint.put("host", "localhost");
+        endpoint.put("port", 9000);
+        final Map<String, Object> credentials = new HashMap<>();
+        credentials.put("accessKey", "login");
+        credentials.put("secretKey", "password");
+
+        try (MockedStatic<CommonConfigurationManager> utilities = Mockito.mockStatic(CommonConfigurationManager.class)) {
+            utilities.when(CommonConfigurationManager::getInstance).thenReturn(commonConfigurationManager);
+            try (MockedStatic<MinioClient> minioUtilities = Mockito.mockStatic(MinioClient.class)) {
+                minioUtilities.when(MinioClient::builder).thenReturn(builderMinio);
+                when(builderMinio
+                    .endpoint(anyString(), anyInt(), anyBoolean())
+                    .credentials(anyString(), anyString())
+                    .build()
+                ).thenReturn(minioClient);
+
+                when(commonConfigurationManager.getConfigValue("externalCsarStore", "endpoint", null)).thenReturn(endpoint);
+                when(commonConfigurationManager.getConfigValue("externalCsarStore", "credentials", null)).thenReturn(credentials);
+                when(commonConfigurationManager.getConfigValue("externalCsarStore", "tempPath", null)).thenReturn("cert/2-file-signed-package");
+                when(commonConfigurationManager.getConfigValue(eq("externalCsarStore"), eq("storageType"), any())).thenReturn(MINIO.name());
+
+                final byte[] packageBytes = getFileBytesOrFail("signed-package-tampered-data.zip");
+
+                when(getObjectArgsBuilder
+                    .bucket(anyString())
+                    .object(anyString())
+                    .build()
+                ).thenReturn(getObjectArgs);
+
+                when(minioClient.getObject(any(GetObjectArgs.class)))
+                    .thenReturn(new GetObjectResponse(null, "bucket", "", "objectName",
+                        new BufferedInputStream(new ByteArrayInputStream(packageBytes))));
+
+                final OnboardPackageInfo onboardPackageInfo = loadSignedPackageWithArtifactInfoS3Store("signed-package-tampered-data.zip",
+                    packageBytes,
+                    null);
+                //no mocked securityManager
+                csarSecurityValidator = new CsarSecurityValidator();
+                Assertions.assertThrows(SecurityManagerException.class, () -> {
+                    csarSecurityValidator.verifyPackageSignature((OnboardSignedPackage) onboardPackageInfo.getOriginalOnboardPackage(),
+                        onboardPackageInfo.getArtifactInfo());
+                });
+            }
+        }
     }
 
     @Test
@@ -148,11 +215,10 @@ class CsarSecurityValidatorTest {
             CsarSecurityValidatorTest.class.getResource(BASE_DIR + path).toURI()));
     }
 
-    private OnboardPackageInfo loadSignedPackageWithArtifactInfo(final String packageName, final byte[] packageBytes,
-                                                                 final CnfPackageValidator cnfPackageValidator) {
+    private OnboardPackageInfo loadSignedPackageWithArtifactInfoS3Store(final String packageName, final byte[] packageBytes,
+                                                                        final CnfPackageValidator cnfPackageValidator) {
         final OnboardingPackageProcessor onboardingPackageProcessor =
-            new OnboardingPackageProcessor(packageName, packageBytes, cnfPackageValidator,
-                new PersistentStorageArtifactInfo(Path.of("src/test/resources/vspmanager.csar/signing/signed-package.zip")));
+            new OnboardingPackageProcessor(packageName, packageBytes, cnfPackageValidator, new MinIoArtifactInfo("bucket", "object"));
         final OnboardPackageInfo onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
         if (onboardPackageInfo == null) {
             fail("Unexpected error. Could not load original package");
index 6dc5517..afc4396 100644 (file)
@@ -22,29 +22,61 @@ package org.openecomp.sdc.vendorsoftwareproduct.security;
 
 import static junit.framework.TestCase.assertEquals;
 import static junit.framework.TestCase.assertTrue;
-
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+import static org.openecomp.sdc.be.csar.storage.StorageFactory.StorageType.MINIO;
+
+import io.minio.GetObjectArgs;
+import io.minio.GetObjectResponse;
+import io.minio.MinioClient;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.nio.file.Files;
-import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.commons.io.FileUtils;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.openecomp.sdc.be.csar.storage.PersistentStorageArtifactInfo;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.openecomp.sdc.be.csar.storage.MinIoArtifactInfo;
+import org.openecomp.sdc.common.CommonConfigurationManager;
 import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.OnboardingPackageProcessor;
 import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.validation.CnfPackageValidator;
 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo;
 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardSignedPackage;
 
+@ExtendWith(MockitoExtension.class)
 class SecurityManagerTest {
 
     private File certDir;
     private String cerDirPath = "/tmp/cert/";
     private SecurityManager securityManager;
+    @Mock
+    private CommonConfigurationManager commonConfigurationManager;
+    @Mock
+    private MinioClient minioClient;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private MinioClient.Builder builderMinio;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private GetObjectArgs.Builder getObjectArgsBuilder;
+    @Mock
+    private GetObjectArgs getObjectArgs;
 
     private File prepareCertFiles(String origFilePath, String newFilePath) throws IOException, URISyntaxException {
         File origFile = new File(getClass().getResource(origFilePath).toURI());
@@ -60,12 +92,14 @@ class SecurityManagerTest {
 
     @BeforeEach
     public void setUp() throws IOException {
+        openMocks(this);
         certDir = new File(cerDirPath);
         if (certDir.exists()) {
             tearDown();
         }
         certDir.mkdirs();
         securityManager = new SecurityManager(certDir.getPath());
+
     }
 
     @AfterEach
@@ -123,18 +157,51 @@ class SecurityManagerTest {
     }
 
     @Test
-    void verifySignedDataTestCertIncludedIntoSignatureArtifactStorageManagerIsEnabled()
-        throws IOException, URISyntaxException, SecurityManagerException {
-        prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
-        byte[] fileToUploadBytes = readAllBytes("/cert/2-file-signed-package/2-file-signed-package.zip");
-
-        final var onboardingPackageProcessor = new OnboardingPackageProcessor("2-file-signed-package.zip", fileToUploadBytes,
-            new CnfPackageValidator(),
-            new PersistentStorageArtifactInfo(Path.of("src/test/resources/cert/2-file-signed-package/2-file-signed-package.zip")));
-        final OnboardPackageInfo onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
-
-        assertTrue(securityManager
-            .verifyPackageSignedData((OnboardSignedPackage) onboardPackageInfo.getOriginalOnboardPackage(), onboardPackageInfo.getArtifactInfo()));
+    void verifySignedDataTestCertIncludedIntoSignatureArtifactStorageManagerIsEnabled() throws Exception {
+
+        final Map<String, Object> endpoint = new HashMap<>();
+        endpoint.put("host", "localhost");
+        endpoint.put("port", 9000);
+        final Map<String, Object> credentials = new HashMap<>();
+        credentials.put("accessKey", "login");
+        credentials.put("secretKey", "password");
+
+        try (MockedStatic<CommonConfigurationManager> utilities = Mockito.mockStatic(CommonConfigurationManager.class)) {
+            utilities.when(CommonConfigurationManager::getInstance).thenReturn(commonConfigurationManager);
+            try (MockedStatic<MinioClient> minioUtilities = Mockito.mockStatic(MinioClient.class)) {
+                minioUtilities.when(MinioClient::builder).thenReturn(builderMinio);
+                when(builderMinio
+                    .endpoint(anyString(), anyInt(), anyBoolean())
+                    .credentials(anyString(), anyString())
+                    .build()
+                ).thenReturn(minioClient);
+
+                when(commonConfigurationManager.getConfigValue("externalCsarStore", "endpoint", null)).thenReturn(endpoint);
+                when(commonConfigurationManager.getConfigValue("externalCsarStore", "credentials", null)).thenReturn(credentials);
+                when(commonConfigurationManager.getConfigValue("externalCsarStore", "tempPath", null)).thenReturn("cert/2-file-signed-package");
+                when(commonConfigurationManager.getConfigValue(eq("externalCsarStore"), eq("storageType"), any())).thenReturn(MINIO.name());
+
+                prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
+                byte[] fileToUploadBytes = readAllBytes("/cert/2-file-signed-package/2-file-signed-package.zip");
+                when(getObjectArgsBuilder
+                    .bucket(anyString())
+                    .object(anyString())
+                    .build()
+                ).thenReturn(getObjectArgs);
+
+                when(minioClient.getObject(any(GetObjectArgs.class)))
+                    .thenReturn(new GetObjectResponse(null, "bucket", "", "objectName",
+                        new BufferedInputStream(new ByteArrayInputStream(fileToUploadBytes))));
+
+                final var onboardingPackageProcessor = new OnboardingPackageProcessor("2-file-signed-package.zip", fileToUploadBytes,
+                    new CnfPackageValidator(), new MinIoArtifactInfo("bucket", "objectName"));
+                final OnboardPackageInfo onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
+
+                assertTrue(securityManager
+                    .verifyPackageSignedData((OnboardSignedPackage) onboardPackageInfo.getOriginalOnboardPackage(),
+                        onboardPackageInfo.getArtifactInfo()));
+            }
+        }
     }
 
     @Test
@@ -158,18 +225,51 @@ class SecurityManagerTest {
     }
 
     @Test
-    void verifySignedDataTestCertNotIncludedIntoSignatureArtifactStorageManagerIsEnabled()
-        throws IOException, URISyntaxException, SecurityManagerException {
-        prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
-        byte[] fileToUploadBytes = readAllBytes("/cert/3-file-signed-package/3-file-signed-package.zip");
-
-        final var onboardingPackageProcessor = new OnboardingPackageProcessor("3-file-signed-package.zip", fileToUploadBytes,
-            new CnfPackageValidator(),
-            new PersistentStorageArtifactInfo(Path.of("src/test/resources/cert/3-file-signed-package/3-file-signed-package.zip")));
-        final OnboardPackageInfo onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
-
-        assertTrue(securityManager
-            .verifyPackageSignedData((OnboardSignedPackage) onboardPackageInfo.getOriginalOnboardPackage(), onboardPackageInfo.getArtifactInfo()));
+    void verifySignedDataTestCertNotIncludedIntoSignatureArtifactStorageManagerIsEnabled() throws Exception {
+
+        final Map<String, Object> endpoint = new HashMap<>();
+        endpoint.put("host", "localhost");
+        endpoint.put("port", 9000);
+        final Map<String, Object> credentials = new HashMap<>();
+        credentials.put("accessKey", "login");
+        credentials.put("secretKey", "password");
+
+        try (MockedStatic<CommonConfigurationManager> utilities = Mockito.mockStatic(CommonConfigurationManager.class)) {
+            utilities.when(CommonConfigurationManager::getInstance).thenReturn(commonConfigurationManager);
+            try (MockedStatic<MinioClient> minioUtilities = Mockito.mockStatic(MinioClient.class)) {
+                minioUtilities.when(MinioClient::builder).thenReturn(builderMinio);
+                when(builderMinio
+                    .endpoint(anyString(), anyInt(), anyBoolean())
+                    .credentials(anyString(), anyString())
+                    .build()
+                ).thenReturn(minioClient);
+
+                when(commonConfigurationManager.getConfigValue("externalCsarStore", "endpoint", null)).thenReturn(endpoint);
+                when(commonConfigurationManager.getConfigValue("externalCsarStore", "credentials", null)).thenReturn(credentials);
+                when(commonConfigurationManager.getConfigValue("externalCsarStore", "tempPath", null)).thenReturn("tempPath");
+                when(commonConfigurationManager.getConfigValue(eq("externalCsarStore"), eq("storageType"), any())).thenReturn(MINIO.name());
+
+                prepareCertFiles("/cert/rootCA.cert", cerDirPath + "root.cert");
+                byte[] fileToUploadBytes = readAllBytes("/cert/3-file-signed-package/3-file-signed-package.zip");
+                when(getObjectArgsBuilder
+                    .bucket(anyString())
+                    .object(anyString())
+                    .build()
+                ).thenReturn(getObjectArgs);
+
+                when(minioClient.getObject(any(GetObjectArgs.class)))
+                    .thenReturn(new GetObjectResponse(null, "bucket", "", "objectName",
+                        new BufferedInputStream(new ByteArrayInputStream(fileToUploadBytes))));
+
+                final var onboardingPackageProcessor = new OnboardingPackageProcessor("3-file-signed-package.zip", fileToUploadBytes,
+                    new CnfPackageValidator(), new MinIoArtifactInfo("bucket", "objectName"));
+                final OnboardPackageInfo onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
+
+                assertTrue(securityManager
+                    .verifyPackageSignedData((OnboardSignedPackage) onboardPackageInfo.getOriginalOnboardPackage(),
+                        onboardPackageInfo.getArtifactInfo()));
+            }
+        }
     }
 
     @Test
index d2c3d10..3b02114 100644 (file)
@@ -1,35 +1,35 @@
 catalogNotificationsConfig:
-    # catalog backend protocol
-    <% if node[:disableHttp] -%>
-    catalogBeProtocol: https
-    <% else %>
-    catalogBeProtocol: http
-    <% end -%>
-    catalogBeHttpPort: <%= @catalog_be_http_port %>
-    catalogBeSslPort: <%= @catalog_be_ssl_port %>
-    catalogBeFqdn: <%= @catalog_be_fqdn %>
-    # do not remove the "" from catalog_notification_url. it is escaping % characters coming from AUTO.json
-    catalogNotificationUrl: "<%= @catalog_notification_url %>"
+  # catalog backend protocol
+  <% if node[:disableHttp] -%>
+  catalogBeProtocol: https
+  <% else %>
+  catalogBeProtocol: http
+  <% end -%>
+  catalogBeHttpPort: <%= @catalog_be_http_port %>
+  catalogBeSslPort: <%= @catalog_be_ssl_port %>
+  catalogBeFqdn: <%= @catalog_be_fqdn %>
+  # do not remove the "" from catalog_notification_url. it is escaping % characters coming from AUTO.json
+  catalogNotificationUrl: "<%= @catalog_notification_url %>"
 
 notifications:
-    pollingIntervalMsec: 2000
-    selectionSize: 100
-    beHost: <%= @onboard_ip %>
-    beHttpPort: <%= @onboard_port %>
+  pollingIntervalMsec: 2000
+  selectionSize: 100
+  beHost: <%= @onboard_ip %>
+  beHttpPort: <%= @onboard_port %>
 
 cassandraConfig:
-    cassandraHosts: [<%= @cassandra_ip %>]
-    cassandraPort: <%= @cassandra_port %>
-    localDataCenter: <%= @DC_NAME %>
-    reconnectTimeout : 30000
-    socketReadTimeout: <%= @socket_read_timeout %>
-    socketConnectTimeout: <%= @socket_connect_timeout %>
-    authenticate: true
-    username: <%= @cassandra_usr %>
-    password: <%= @cassandra_pwd %>
-    ssl: <%= @cassandra_ssl_enabled %>
-    truststorePath: <%= node['jetty']['truststore_path'] %>
-    truststorePassword: <%= @cassandra_truststore_password %>
+  cassandraHosts: [ <%= @cassandra_ip %> ]
+  cassandraPort: <%= @cassandra_port %>
+  localDataCenter: <%= @DC_NAME %>
+  reconnectTimeout: 30000
+  socketReadTimeout: <%= @socket_read_timeout %>
+  socketConnectTimeout: <%= @socket_connect_timeout %>
+  authenticate: true
+  username: <%= @cassandra_usr %>
+  password: <%= @cassandra_pwd %>
+  ssl: <%= @cassandra_ssl_enabled %>
+  truststorePath: <%= node['jetty']['truststore_path'] %>
+  truststorePassword: <%= @cassandra_truststore_password %>
 
 # access restriction
 authCookie:
@@ -42,8 +42,8 @@ authCookie:
   isHttpOnly: true
   # redirect variable name from portal.properties file
   redirectURL: "redirect_url"
-  excludedUrls: ['/.*']
-  onboardingExcludedUrls: ['/.*']
+  excludedUrls: [ '/.*' ]
+  onboardingExcludedUrls: [ '/.*' ]
 
 basicAuth:
   enabled: <%= @basic_auth_enabled %>
@@ -55,9 +55,16 @@ zipValidation:
   ignoreManifest: false
 
 externalCsarStore:
-  storeCsarsExternally: false
-  fullPath: "/home/onap/temp/"
+  storageType: NONE # NONE, MINIO
+  endpoint:
+    host: 127.0.0.1
+    port: 9000
+    secure: false
+  credentials:
+    accessKey: "login"
+    secretKey: "password"
   foldersToStrip:
     - Files/images
   sizeLimit: 10000000
-  thresholdEntries: 10000
\ No newline at end of file
+  thresholdEntries: 10000
+  tempPath: "/home/onap/temp/"
index 28ce5d2..21ad7a6 100644 (file)
@@ -202,11 +202,10 @@ public enum Messages {
     FAILED_TO_MARK_NOTIFICATION_AS_READ("Failed to mark notifications as read"),
     FAILED_TO_UPDATE_LAST_SEEN_NOTIFICATION("Failed to update last seen notification for user %s"),
     FAILED_TO_VERIFY_SIGNATURE("Could not verify signature of signed package."),
-    EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING_FULL_PATH("externalCsarStore configuration failure, missing 'fullPath'"),
+    EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING("externalCsarStore configuration failure, missing '%s'"),
     ERROR_HAS_OCCURRED_WHILE_PERSISTING_THE_ARTIFACT("An error has occurred while persisting the artifact: %s"),
     ERROR_HAS_OCCURRED_WHILE_REDUCING_THE_ARTIFACT_SIZE("An error has occurred while reducing the artifact's size: %s"),
-    UNEXPECTED_PROBLEM_HAPPENED_WHILE_GETTING("An unexpected problem happened while getting '%s'"),
-    PERSISTENCE_STORE_IS_DOWN_OR_NOT_AVAILABLE("Persistence store is down or not available. Error: '%s'");
+    UNEXPECTED_PROBLEM_HAPPENED_WHILE_GETTING("An unexpected problem happened while getting '%s'");
     // @formatter:on
 
     private String errorMessage;
index e5c5996..fbb25de 100644 (file)
@@ -31,7 +31,6 @@ import com.amdocs.zusammen.utils.fileutils.FileUtils;
 import java.io.ByteArrayInputStream;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
-import java.nio.file.Path;
 import java.util.Optional;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
@@ -39,12 +38,8 @@ import org.openecomp.core.utilities.json.JsonUtil;
 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
 import org.openecomp.core.zusammen.api.ZusammenAdaptor;
 import org.openecomp.sdc.be.csar.storage.ArtifactInfo;
-import org.openecomp.sdc.be.csar.storage.ArtifactStorageConfig;
 import org.openecomp.sdc.be.csar.storage.ArtifactStorageManager;
-import org.openecomp.sdc.be.csar.storage.PersistentVolumeArtifactStorageConfig;
-import org.openecomp.sdc.be.csar.storage.PersistentVolumeArtifactStorageManager;
-import org.openecomp.sdc.common.CommonConfigurationManager;
-import org.openecomp.sdc.common.errors.Messages;
+import org.openecomp.sdc.be.csar.storage.StorageFactory;
 import org.openecomp.sdc.datatypes.model.ElementType;
 import org.openecomp.sdc.heat.datatypes.structure.ValidationStructureList;
 import org.openecomp.sdc.logging.api.Logger;
@@ -56,15 +51,15 @@ import org.openecomp.sdc.versioning.dao.types.Version;
 
 public class OrchestrationTemplateCandidateDaoZusammenImpl implements OrchestrationTemplateCandidateDao {
 
-    private static final Logger logger = LoggerFactory.getLogger(OrchestrationTemplateCandidateDaoZusammenImpl.class);
+    private static final Logger LOGGER = LoggerFactory.getLogger(OrchestrationTemplateCandidateDaoZusammenImpl.class);
     private static final String EMPTY_DATA = "{}";
-    private static final String EXTERNAL_CSAR_STORE = "externalCsarStore";
     private final ZusammenAdaptor zusammenAdaptor;
     private final ArtifactStorageManager artifactStorageManager;
 
     public OrchestrationTemplateCandidateDaoZusammenImpl(final ZusammenAdaptor zusammenAdaptor) {
         this.zusammenAdaptor = zusammenAdaptor;
-        this.artifactStorageManager = new PersistentVolumeArtifactStorageManager(readArtifactStorageConfiguration());
+        LOGGER.info("Instantiating artifactStorageManager");
+        this.artifactStorageManager = new StorageFactory().createArtifactStorageManager();
     }
 
     @Override
@@ -74,14 +69,14 @@ public class OrchestrationTemplateCandidateDaoZusammenImpl implements Orchestrat
 
     @Override
     public Optional<OrchestrationTemplateCandidateData> get(String vspId, Version version) {
-        logger.info("Getting orchestration template for vsp id {}", vspId);
+        LOGGER.info("Getting orchestration template for vsp id {}", vspId);
         SessionContext context = createSessionContext();
         ElementContext elementContext = new ElementContext(vspId, version.getId());
         Optional<Element> candidateElement = zusammenAdaptor
             .getElementByName(context, elementContext, null, ElementType.OrchestrationTemplateCandidate.name());
         if (!candidateElement.isPresent() || VspZusammenUtil.hasEmptyData(candidateElement.get().getData()) || candidateElement.get().getSubElements()
             .isEmpty()) {
-            logger.info("Orchestration template for vsp id {} does not exist / has empty data", vspId);
+            LOGGER.info("Orchestration template for vsp id {} does not exist / has empty data", vspId);
             return Optional.empty();
         }
         OrchestrationTemplateCandidateData candidate = new OrchestrationTemplateCandidateData();
@@ -89,26 +84,26 @@ public class OrchestrationTemplateCandidateDaoZusammenImpl implements Orchestrat
         candidateElement.get().getSubElements().stream()
             .map(element -> zusammenAdaptor.getElement(context, elementContext, element.getElementId().toString()))
             .forEach(element -> element.ifPresent(candidateInfoElement -> populateCandidate(candidate, candidateInfoElement, true)));
-        logger.info("Finished getting orchestration template for vsp id {}", vspId);
+        LOGGER.info("Finished getting orchestration template for vsp id {}", vspId);
         return candidate.getFileSuffix() == null ? Optional.empty() : Optional.of(candidate);
     }
 
     @Override
     public Optional<OrchestrationTemplateCandidateData> getInfo(String vspId, Version version) {
-        logger.info("Getting orchestration template info for vsp id {}", vspId);
+        LOGGER.info("Getting orchestration template info for vsp id {}", vspId);
         SessionContext context = createSessionContext();
         ElementContext elementContext = new ElementContext(vspId, version.getId());
         Optional<ElementInfo> candidateElement = zusammenAdaptor
             .getElementInfoByName(context, elementContext, null, ElementType.OrchestrationTemplateCandidate.name());
         if (!candidateElement.isPresent() || candidateElement.get().getSubElements().isEmpty()) {
-            logger.info("Orchestration template info for vsp id {} does not exist", vspId);
+            LOGGER.info("Orchestration template info for vsp id {} does not exist", vspId);
             return Optional.empty();
         }
         OrchestrationTemplateCandidateData candidate = new OrchestrationTemplateCandidateData();
         candidateElement.get().getSubElements().stream()
             .map(elementInfo -> zusammenAdaptor.getElement(context, elementContext, elementInfo.getId().toString()))
             .forEach(element -> element.ifPresent(candidateInfoElement -> populateCandidate(candidate, candidateInfoElement, false)));
-        logger.info("Finished getting orchestration template info for vsp id {}", vspId);
+        LOGGER.info("Finished getting orchestration template info for vsp id {}", vspId);
         return candidate.getFileSuffix() == null ? Optional.empty() : Optional.of(candidate);
     }
 
@@ -149,7 +144,7 @@ public class OrchestrationTemplateCandidateDaoZusammenImpl implements Orchestrat
 
     @Override
     public void update(final String vspId, final Version version, final OrchestrationTemplateCandidateData candidateData) {
-        logger.info("Uploading candidate data entity for vsp id {}", vspId);
+        LOGGER.info("Uploading candidate data entity for vsp id {}", vspId);
         final ZusammenElement candidateElement = buildStructuralElement(ElementType.OrchestrationTemplateCandidate, Action.UPDATE);
         candidateElement.setData(new ByteArrayInputStream(candidateData.getFilesDataStructure().getBytes()));
         final ZusammenElement candidateContentElement = buildStructuralElement(ElementType.OrchestrationTemplateCandidateContent, Action.UPDATE);
@@ -170,7 +165,7 @@ public class OrchestrationTemplateCandidateDaoZusammenImpl implements Orchestrat
                     throw new OrchestrationTemplateCandidateDaoZusammenException("No artifact info provided");
                 }
                 final ArtifactInfo artifactInfo = artifactStorageManager.persist(vspId, versionId, candidateArtifactInfo);
-                originalPackageElement.setData(new ByteArrayInputStream(artifactInfo.getPath().toString().getBytes(StandardCharsets.UTF_8)));
+                originalPackageElement.setData(new ByteArrayInputStream(artifactInfo.getInfo().getBytes(StandardCharsets.UTF_8)));
             } else {
                 originalPackageElement.setData(new ByteArrayInputStream(candidateData.getOriginalFileContentData().array()));
             }
@@ -185,12 +180,12 @@ public class OrchestrationTemplateCandidateDaoZusammenImpl implements Orchestrat
         final var context = createSessionContext();
         final var elementContext = new ElementContext(vspId, versionId);
         zusammenAdaptor.saveElement(context, elementContext, candidateElement, "Update Orchestration Template Candidate");
-        logger.info("Finished uploading candidate data entity for vsp id {}", vspId);
+        LOGGER.info("Finished uploading candidate data entity for vsp id {}", vspId);
     }
 
     @Override
     public void updateValidationData(String vspId, Version version, ValidationStructureList validationData) {
-        logger.info("Updating validation data of orchestration template candidate for VSP id {} ", vspId);
+        LOGGER.info("Updating validation data of orchestration template candidate for VSP id {} ", vspId);
         ZusammenElement validationDataElement = buildStructuralElement(ElementType.OrchestrationTemplateCandidateValidationData, Action.UPDATE);
         validationDataElement.setData(validationData == null ? new ByteArrayInputStream(EMPTY_DATA.getBytes())
             : new ByteArrayInputStream(JsonUtil.object2Json(validationData).getBytes()));
@@ -199,23 +194,23 @@ public class OrchestrationTemplateCandidateDaoZusammenImpl implements Orchestrat
         SessionContext context = createSessionContext();
         ElementContext elementContext = new ElementContext(vspId, version.getId());
         zusammenAdaptor.saveElement(context, elementContext, candidateElement, "Update Orchestration Template Candidate validation data");
-        logger.info("Finished updating validation data of orchestration template candidate for VSP id {}", vspId);
+        LOGGER.info("Finished updating validation data of orchestration template candidate for VSP id {}", vspId);
     }
 
     @Override
     public void updateStructure(String vspId, Version version, FilesDataStructure fileDataStructure) {
-        logger.info("Updating orchestration template for VSP id {}", vspId);
+        LOGGER.info("Updating orchestration template for VSP id {}", vspId);
         ZusammenElement candidateElement = buildStructuralElement(ElementType.OrchestrationTemplateCandidate, Action.UPDATE);
         candidateElement.setData(new ByteArrayInputStream(JsonUtil.object2Json(fileDataStructure).getBytes()));
         SessionContext context = createSessionContext();
         ElementContext elementContext = new ElementContext(vspId, version.getId());
         zusammenAdaptor.saveElement(context, elementContext, candidateElement, "Update Orchestration Template Candidate structure");
-        logger.info("Finished uploading candidate data entity for vsp id {}", vspId);
+        LOGGER.info("Finished uploading candidate data entity for vsp id {}", vspId);
     }
 
     @Override
     public Optional<String> getStructure(String vspId, Version version) {
-        logger.info("Getting orchestration template candidate structure for vsp id {}", vspId);
+        LOGGER.info("Getting orchestration template candidate structure for vsp id {}", vspId);
         SessionContext context = createSessionContext();
         ElementContext elementContext = new ElementContext(vspId, version.getId());
         Optional<Element> element = zusammenAdaptor
@@ -223,24 +218,10 @@ public class OrchestrationTemplateCandidateDaoZusammenImpl implements Orchestrat
         if (element.isPresent() && !VspZusammenUtil.hasEmptyData(element.get().getData())) {
             return Optional.of(new String(FileUtils.toByteArray(element.get().getData())));
         }
-        logger.info("Finished getting orchestration template candidate structure for vsp id {}", vspId);
+        LOGGER.info("Finished getting orchestration template candidate structure for vsp id {}", vspId);
         return Optional.empty();
     }
 
-    private ArtifactStorageConfig readArtifactStorageConfiguration() {
-        final var commonConfigurationManager = CommonConfigurationManager.getInstance();
-        final boolean isEnabled = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "storeCsarsExternally", false);
-        logger.info("ArtifactConfig.isEnabled: '{}'", isEnabled);
-        final String storagePathString = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "fullPath", null);
-        logger.info("ArtifactConfig.storagePath: '{}'", storagePathString);
-        if (isEnabled && storagePathString == null) {
-            throw new OrchestrationTemplateCandidateDaoZusammenException(
-                Messages.EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING_FULL_PATH.getErrorMessage());
-        }
-        final var storagePath = storagePathString == null ? null : Path.of(storagePathString);
-        return new PersistentVolumeArtifactStorageConfig(isEnabled, storagePath);
-    }
-
     @Getter
     @AllArgsConstructor
     private enum InfoPropertyName {