From 22360c78d550a25b9bdaea12cdb208371b69a488 Mon Sep 17 00:00:00 2001 From: "andre.schmid" Date: Fri, 12 Jul 2019 12:33:10 +0000 Subject: Allow relative path for SOL004 descriptors import Allow the use of relative path on SOL004 descriptors imports. Resolves imports with "/", "../" or "./" entries during validation and package processing. Validate if the reference is inside the package. Fix problem where imported descriptor files, described as a non string scalar yaml entry, were not being checked by the validator. Change-Id: Ie5a32736b6090b4adf178e8714f7460bcd068def Issue-ID: SDC-2422 Signed-off-by: andre.schmid --- .../validation/SOL004MetaDirectoryValidator.java | 88 +++------------- .../SOL004MetaDirectoryValidatorTest.java | 116 +++++++++++++++++++-- .../definition/definitionFileWithOneImport.yaml | 6 ++ .../definition/sampleDefinitionFile3.yaml | 6 -- 4 files changed, 130 insertions(+), 86 deletions(-) create mode 100644 openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/validation.files/definition/definitionFileWithOneImport.yaml delete mode 100644 openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/validation.files/definition/sampleDefinitionFile3.yaml (limited to 'openecomp-be/backend/openecomp-sdc-vendor-software-product-manager') diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004MetaDirectoryValidator.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004MetaDirectoryValidator.java index d41d39cf66..2bd28b389b 100644 --- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004MetaDirectoryValidator.java +++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004MetaDirectoryValidator.java @@ -20,9 +20,8 @@ package org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation; -import java.util.Collection; -import org.openecomp.core.converter.ServiceTemplateReaderService; -import org.openecomp.core.impl.services.ServiceTemplateReaderServiceImpl; +import org.apache.commons.collections.CollectionUtils; +import org.openecomp.core.impl.ToscaDefinitionImportHandler; import org.openecomp.core.utilities.file.FileContentHandler; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.common.errors.Messages; @@ -38,6 +37,7 @@ import org.openecomp.sdc.tosca.csar.ToscaMetadata; import org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.exceptions.InvalidManifestMetadataException; import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -52,7 +52,6 @@ import static org.openecomp.sdc.tosca.csar.CSARConstants.CSAR_VERSION_1_1; import static org.openecomp.sdc.tosca.csar.CSARConstants.MANIFEST_METADATA_LIMIT; import static org.openecomp.sdc.tosca.csar.CSARConstants.MANIFEST_PNF_METADATA; import static org.openecomp.sdc.tosca.csar.CSARConstants.MANIFEST_VNF_METADATA; -import static org.openecomp.sdc.tosca.csar.CSARConstants.NON_FILE_IMPORT_ATTRIBUTES; import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_MANIFEST_FILE_EXT; import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ETSI_ENTRY_CERTIFICATE; import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_FILE_VERSION_ENTRY; @@ -71,17 +70,14 @@ import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_TYPE_VNF; /** * Validates the contents of the package to ensure it complies with the "CSAR with TOSCA-Metadata directory" structure * as defined in ETSI GS NFV-SOL 004 v2.6.1. - * */ - -class SOL004MetaDirectoryValidator implements Validator{ +class SOL004MetaDirectoryValidator implements Validator { private static final Logger LOGGER = LoggerFactory.getLogger(SOL004MetaDirectoryValidator.class); private static final String MANIFEST_SOURCE = "Source"; private static final String MANIFEST_NON_MANO_SOURCE = "Non-MANO Source"; private final List errorsByFile = new ArrayList<>(); - private final Set verifiedImports = new HashSet<>(); @Override public Map> validateContent(FileContentHandler contentHandler, List folderList) { @@ -119,11 +115,11 @@ class SOL004MetaDirectoryValidator implements Validator{ } public String getFileExtension(String filePath){ - return filePath.substring(filePath.lastIndexOf(".") + 1); + return filePath.substring(filePath.lastIndexOf('.') + 1); } private String getFileName(String filePath){ - return filePath.substring(filePath.lastIndexOf("/") + 1, filePath.lastIndexOf(".")); + return filePath.substring(filePath.lastIndexOf('/') + 1, filePath.lastIndexOf('.')); } private boolean hasETSIMetadata(ToscaMetadata toscaMetadata){ @@ -213,78 +209,28 @@ class SOL004MetaDirectoryValidator implements Validator{ || CSAR_VERSION_1_0.equals(version)); } - private void validateDefinitionFile(FileContentHandler contentHandler, String filePath) { - Set existingFiles = contentHandler.getFileList(); + private void validateDefinitionFile(final FileContentHandler contentHandler, final String filePath) { + final Set existingFiles = contentHandler.getFileList(); if (verifyFileExists(existingFiles, filePath)) { - byte[] definitionFile = getFileContent(filePath, contentHandler); - handleImports(contentHandler, filePath, existingFiles, definitionFile); - }else{ - reportError(ErrorLevel.ERROR, String.format(Messages.MISSING_DEFINITION_FILE.getErrorMessage(), filePath)); - } - } - - private void handleImports(FileContentHandler contentHandler, String filePath, Set existingFiles, - byte[] definitionFile) { - try { - ServiceTemplateReaderService readerService = new ServiceTemplateReaderServiceImpl(definitionFile); - List imports = (readerService).getImports(); - for (Object o : imports) { - String rootDir = "/"; - if (filePath.contains("/")) { - rootDir = filePath.substring(0, filePath.lastIndexOf("/")); - } - String verifiedFile = verifyImport(existingFiles, o, rootDir); - if (verifiedFile != null && !verifiedImports.contains(verifiedFile)) { - verifiedImports.add(verifiedFile); - handleImports(contentHandler, verifiedFile, existingFiles, getFileContent(verifiedFile, - contentHandler)); - } + final ToscaDefinitionImportHandler toscaDefinitionImportHandler = + new ToscaDefinitionImportHandler(contentHandler.getFiles(), filePath); + final List validationErrorList = toscaDefinitionImportHandler.getErrors(); + if (CollectionUtils.isNotEmpty(validationErrorList)) { + errorsByFile.addAll(validationErrorList); } + } else { + reportError(ErrorLevel.ERROR, String.format(Messages.MISSING_DEFINITION_FILE.getErrorMessage(), filePath)); } - catch (Exception e){ - reportError(ErrorLevel.ERROR, String.format(Messages.INVALID_YAML_FORMAT.getErrorMessage(), e.getMessage())); - LOGGER.error("{}", Messages.INVALID_YAML_FORMAT_REASON, e.getMessage(), e); - } - } - - private String verifyImport(Set existingFiles, Object o, String parentDir) { - if(o instanceof String){ - String filePath = ((String) o); - if(!filePath.contains("/")){ - filePath = parentDir + "/" + filePath; - } - if(!verifyFileExists(existingFiles, filePath)){ - reportError(ErrorLevel.ERROR, String.format(Messages.MISSING_IMPORT_FILE.getErrorMessage(), filePath, - parentDir)); - return null; - } - return filePath; - } else if(o instanceof Map){ - Map o1 = (Map)o; - for(Map.Entry entry: o1.entrySet()){ - if(NON_FILE_IMPORT_ATTRIBUTES.stream().noneMatch(attr -> entry.getKey().equals(attr))){ - verifyImport(existingFiles, entry.getValue(), parentDir); - } - } - }else { - reportError(ErrorLevel.ERROR, String.format(Messages.INVALID_IMPORT_STATEMENT.getErrorMessage(), parentDir)); - } - return null; } private boolean verifyFileExists(Set existingFiles, String filePath){ return existingFiles.contains(filePath); } - private byte[] getFileContent(String filename, FileContentHandler contentHandler){ - Map files = contentHandler.getFiles(); - return files.get(filename); - } - private void validateManifestFile(FileContentHandler contentHandler, String filePath){ final Set existingFiles = contentHandler.getFileList(); - if(verifyFileExists(existingFiles, filePath)) { + if (verifyFileExists(existingFiles, filePath)) { Manifest onboardingManifest = new SOL004ManifestOnboarding(); onboardingManifest.parse(contentHandler.getFileContent(filePath)); if(onboardingManifest.isValid()){ @@ -419,7 +365,7 @@ class SOL004MetaDirectoryValidator implements Validator{ } } - private void reportError(ErrorLevel errorLevel, String errorMessage){ + private void reportError(final ErrorLevel errorLevel, final String errorMessage) { errorsByFile.add(new ErrorMessage(errorLevel, errorMessage)); } diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004MetaDirectoryValidatorTest.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004MetaDirectoryValidatorTest.java index 06b4a02cc7..6a56db6e34 100644 --- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004MetaDirectoryValidatorTest.java +++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004MetaDirectoryValidatorTest.java @@ -24,6 +24,7 @@ import org.apache.commons.collections.CollectionUtils; import org.junit.Before; import org.junit.Test; import org.openecomp.core.utilities.file.FileContentHandler; +import org.openecomp.sdc.common.errors.Messages; import org.openecomp.sdc.common.utils.SdcCommon; import org.openecomp.sdc.datatypes.error.ErrorLevel; import org.openecomp.sdc.datatypes.error.ErrorMessage; @@ -33,10 +34,19 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import org.openecomp.sdc.logging.api.Logger; +import org.openecomp.sdc.logging.api.LoggerFactory; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.openecomp.sdc.tosca.csar.CSARConstants.PNFD_NAME; +import static org.openecomp.sdc.tosca.csar.CSARConstants.PNFD_PROVIDER; +import static org.openecomp.sdc.tosca.csar.CSARConstants.PNFD_ARCHIVE_VERSION; +import static org.openecomp.sdc.tosca.csar.CSARConstants.PNFD_RELEASE_DATE_TIME; import static org.openecomp.sdc.tosca.csar.CSARConstants.SEPARATOR_MF_ATTRIBUTE; import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ENTRY_DEFINITIONS; import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ETSI_ENTRY_CERTIFICATE; @@ -45,10 +55,6 @@ import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ETSI_ENTRY_L import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ETSI_ENTRY_MANIFEST; import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ETSI_ENTRY_TESTS; import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_PATH_FILE_NAME; -import static org.openecomp.sdc.tosca.csar.CSARConstants.PNFD_NAME; -import static org.openecomp.sdc.tosca.csar.CSARConstants.PNFD_PROVIDER; -import static org.openecomp.sdc.tosca.csar.CSARConstants.PNFD_ARCHIVE_VERSION; -import static org.openecomp.sdc.tosca.csar.CSARConstants.PNFD_RELEASE_DATE_TIME; import static org.openecomp.sdc.tosca.csar.CSARConstants.VNF_PRODUCT_NAME; import static org.openecomp.sdc.tosca.csar.CSARConstants.VNF_PROVIDER_ID; import static org.openecomp.sdc.tosca.csar.CSARConstants.VNF_PACKAGE_VERSION; @@ -58,6 +64,8 @@ import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.va public class SOL004MetaDirectoryValidatorTest { + private static final Logger LOGGER = LoggerFactory.getLogger(SOL004MetaDirectoryValidatorTest.class); + private SOL004MetaDirectoryValidator sol004MetaDirectoryValidator; private FileContentHandler handler; private String metaFile; @@ -225,7 +233,7 @@ public class SOL004MetaDirectoryValidatorTest { handler.addFile("Definitions/etsi_nfv_sol001_pnfd_2_5_1_types.yaml", sampleDefinitionFile2); manifestBuilder.withSource("Definitions/etsi_nfv_sol001_pnfd_2_5_1_types.yaml"); - final byte [] sampleDefinitionFile3 = getResourceBytes("/validation.files/definition/sampleDefinitionFile3.yaml"); + final byte [] sampleDefinitionFile3 = getResourceBytes("/validation.files/definition/sampleDefinitionFile1.yaml"); handler.addFile("Definitions/etsi_nfv_sol001_pnfd_2_5_2_types.yaml", sampleDefinitionFile3); manifestBuilder.withSource("Definitions/etsi_nfv_sol001_pnfd_2_5_2_types.yaml"); @@ -487,7 +495,7 @@ public class SOL004MetaDirectoryValidatorTest { @Test public void testGivenManifestFile_withValidVnfMetadata_thenNoErrorsReturned() { final ManifestBuilder manifestBuilder = getVnfManifestSampleBuilder(); - + handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFile.getBytes(StandardCharsets.UTF_8)); manifestBuilder.withSource(TOSCA_META_PATH_FILE_NAME); handler.addFile(TOSCA_CHANGELOG_FILEPATH, "".getBytes()); @@ -675,6 +683,80 @@ public class SOL004MetaDirectoryValidatorTest { } + /** + * Tests an imported descriptor with a missing imported file. + */ + @Test + public void testGivenDefinitionFileWithImportedDescriptor_whenImportedDescriptorImportsMissingFile_thenMissingImportErrorOccur() throws IOException { + final ManifestBuilder manifestBuilder = getVnfManifestSampleBuilder(); + + handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFile.getBytes(StandardCharsets.UTF_8)); + manifestBuilder.withSource(TOSCA_META_PATH_FILE_NAME); + + handler.addFile(TOSCA_CHANGELOG_FILEPATH, "".getBytes(StandardCharsets.UTF_8)); + manifestBuilder.withSource(TOSCA_CHANGELOG_FILEPATH); + + handler.addFile(SAMPLE_SOURCE, "".getBytes()); + manifestBuilder.withSource(SAMPLE_SOURCE); + + final String definitionImportOne = "Definitions/importOne.yaml"; + handler.addFile(definitionImportOne, getResourceBytes("/validation.files/definition/sampleDefinitionFile2.yaml")); + manifestBuilder.withSource(definitionImportOne); + + final String definitionFileWithValidImports = "/validation.files/definition/definitionFileWithOneImport.yaml"; + handler.addFile(TOSCA_DEFINITION_FILEPATH, getResourceBytes(definitionFileWithValidImports)); + manifestBuilder.withSource(TOSCA_DEFINITION_FILEPATH); + + manifestBuilder.withSource(TOSCA_MANIFEST_FILEPATH); + handler.addFile(TOSCA_MANIFEST_FILEPATH, manifestBuilder.build().getBytes(StandardCharsets.UTF_8)); + + final Map> actualErrorMap = sol004MetaDirectoryValidator.validateContent(handler, Collections.emptyList()); + + final List expectedErrorList = new ArrayList<>(); + expectedErrorList.add(new ErrorMessage(ErrorLevel.ERROR + , Messages.MISSING_IMPORT_FILE.formatMessage("Definitions/etsi_nfv_sol001_pnfd_2_5_2_types.yaml")) + ); + + assertExpectedErrors(actualErrorMap.get(SdcCommon.UPLOAD_FILE), expectedErrorList); + } + + /** + * Tests an imported descriptor with invalid import statement. + */ + @Test + public void testGivenDefinitionFileWithImportedDescriptor_whenInvalidImportStatementExistInImportedDescriptor_thenInvalidImportErrorOccur() { + final ManifestBuilder manifestBuilder = getVnfManifestSampleBuilder(); + + handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFile.getBytes(StandardCharsets.UTF_8)); + manifestBuilder.withSource(TOSCA_META_PATH_FILE_NAME); + + handler.addFile(TOSCA_CHANGELOG_FILEPATH, "".getBytes(StandardCharsets.UTF_8)); + manifestBuilder.withSource(TOSCA_CHANGELOG_FILEPATH); + + handler.addFile(SAMPLE_SOURCE, "".getBytes()); + manifestBuilder.withSource(SAMPLE_SOURCE); + + final String definitionImportOne = "Definitions/importOne.yaml"; + handler.addFile(definitionImportOne, getResourceBytes("/validation.files/definition/definitionFileWithInvalidImport.yaml")); + manifestBuilder.withSource(definitionImportOne); + + final String definitionFileWithValidImports = "/validation.files/definition/definitionFileWithOneImport.yaml"; + handler.addFile(TOSCA_DEFINITION_FILEPATH, getResourceBytes(definitionFileWithValidImports)); + manifestBuilder.withSource(TOSCA_DEFINITION_FILEPATH); + + manifestBuilder.withSource(TOSCA_MANIFEST_FILEPATH); + handler.addFile(TOSCA_MANIFEST_FILEPATH, manifestBuilder.build().getBytes(StandardCharsets.UTF_8)); + + final Map> actualErrorMap = sol004MetaDirectoryValidator.validateContent(handler, Collections.emptyList()); + + final List expectedErrorList = new ArrayList<>(); + expectedErrorList.add(new ErrorMessage(ErrorLevel.ERROR + , Messages.INVALID_IMPORT_STATEMENT.formatMessage(definitionImportOne, "null")) + ); + + assertExpectedErrors(actualErrorMap.get(SdcCommon.UPLOAD_FILE), expectedErrorList); + } + private void assertExpectedErrors(final String testCase, final Map> errors, final int expectedErrors){ final List errorMessages = errors.get(SdcCommon.UPLOAD_FILE); printErrorMessages(errorMessages); @@ -697,8 +779,9 @@ public class SOL004MetaDirectoryValidatorTest { try { return ValidatorUtil.getFileResource(resourcePath); } catch (final IOException e) { - fail(String.format("Could not load resource '%s'", resourcePath)); - e.printStackTrace(); + final String errorMsg = String.format("Could not load resource '%s'", resourcePath); + LOGGER.error(errorMsg, e); + fail(errorMsg); } return null; @@ -719,4 +802,19 @@ public class SOL004MetaDirectoryValidatorTest { .withMetaData(VNF_PACKAGE_VERSION, "1.0") .withMetaData(VNF_RELEASE_DATE_TIME, "2019-03-11T11:25:00+00:00"); } -} + + private void assertExpectedErrors(List actualErrorList, final List expectedErrorList) { + if (actualErrorList == null) { + actualErrorList = new ArrayList<>(); + } + + assertThat("The actual error list should have the same size as the expected error list" + , actualErrorList, hasSize(expectedErrorList.size()) + ); + + assertThat("The actual error and expected error lists should be the same" + , actualErrorList, containsInAnyOrder(expectedErrorList.toArray(new ErrorMessage[0])) + ); + } + +} \ No newline at end of file diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/validation.files/definition/definitionFileWithOneImport.yaml b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/validation.files/definition/definitionFileWithOneImport.yaml new file mode 100644 index 0000000000..35b561e20d --- /dev/null +++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/validation.files/definition/definitionFileWithOneImport.yaml @@ -0,0 +1,6 @@ +tosca_definitions_version: tosca_simple_yaml_1_2 + +description: example definition file for testing + +imports: + - importOne.yaml diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/validation.files/definition/sampleDefinitionFile3.yaml b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/validation.files/definition/sampleDefinitionFile3.yaml deleted file mode 100644 index 4df199d767..0000000000 --- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/validation.files/definition/sampleDefinitionFile3.yaml +++ /dev/null @@ -1,6 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_2 - -description: example definition file for testing - -imports: - - etsi_nfv_sol001_pnfd_2_5_1_types.yaml \ No newline at end of file -- cgit 1.2.3-korg