From 19773b769c6762a12876064c70a34cc31d2b12da Mon Sep 17 00:00:00 2001 From: "andre.schmid" Date: Thu, 26 Sep 2019 13:22:44 +0100 Subject: Validate SOL004 manifest signature order SOL004 Manifest signature must be the last entry of the manifest. Change-Id: Ie3835f7140ccdf92ef5518ca2d7571930de81971 Issue-ID: SDC-2587 Signed-off-by: andre.schmid --- .../org/openecomp/sdc/common/errors/Messages.java | 3 +- .../sdc/tosca/csar/AbstractOnboardingManifest.java | 5 ++++ .../org/openecomp/sdc/tosca/csar/Manifest.java | 2 ++ .../sdc/tosca/csar/SOL004ManifestOnboarding.java | 26 +++++++++++----- .../tosca/csar/SOL004ManifestOnboardingTest.java | 27 ++++++++++------- .../manifest/invalid/double-signed.mf | 35 ---------------------- .../manifest/valid/signed-with-non-mano.mf | 12 ++++---- 7 files changed, 51 insertions(+), 59 deletions(-) delete mode 100644 openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/double-signed.mf (limited to 'openecomp-be/lib') diff --git a/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/errors/Messages.java b/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/errors/Messages.java index 2e30126985..7163dbecfd 100644 --- a/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/errors/Messages.java +++ b/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/errors/Messages.java @@ -47,7 +47,8 @@ public enum Messages { MANIFEST_EXPECTED_SOURCE_PATH("Expected Source entry path"), MANIFEST_EXPECTED_ALGORITHM_VALUE("Expected Algorithm entry value"), MANIFEST_EXPECTED_ALGORITHM_BEFORE_HASH("Expected 'Algorithm' entry before 'Hash' entry"), - MANIFEST_DUPLICATED_CMS_SIGNATURE("Duplicated CMS signature"), + MANIFEST_SIGNATURE_DUPLICATED("Duplicated manifest signature"), + MANIFEST_SIGNATURE_LAST_ENTRY("The manifest signature must be the last entry of the manifest."), MANIFEST_METADATA_DOES_NOT_MATCH_LIMIT("Manifest metadata must only have the required number [%s] of entries"), MANIFEST_EMPTY("The manifest is empty"), MANIFEST_ERROR_WITH_LINE("%s;%nAt line %s: '%s'."), diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/AbstractOnboardingManifest.java b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/AbstractOnboardingManifest.java index 7cc11e564d..326eb6a517 100644 --- a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/AbstractOnboardingManifest.java +++ b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/AbstractOnboardingManifest.java @@ -371,6 +371,11 @@ abstract class AbstractOnboardingManifest implements Manifest { return ImmutableMap.copyOf(nonManoSources); } + @Override + public boolean isSigned() { + return getCmsSignature().isPresent(); + } + @Override public Optional getCmsSignature() { return Optional.ofNullable(cmsSignature); diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/Manifest.java b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/Manifest.java index c0ccbbc14d..31b04f0d8b 100644 --- a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/Manifest.java +++ b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/Manifest.java @@ -71,6 +71,8 @@ public interface Manifest { */ Optional getType(); + boolean isSigned(); + /** * Gets the CMS manifest signature if present in manifest * @return diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboarding.java b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboarding.java index bb0b07a63f..8e67d7b5de 100644 --- a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboarding.java +++ b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboarding.java @@ -80,7 +80,6 @@ public class SOL004ManifestOnboarding extends AbstractOnboardingManifest { break; case NON_MANO_ARTIFACT_SETS: processNonManoArtifactEntry(); - continueToProcess = false; break; case SOURCE: processSource(); @@ -100,6 +99,9 @@ public class SOL004ManifestOnboarding extends AbstractOnboardingManifest { Optional currentLine = readNextNonEmptyLine(); while (currentLine.isPresent()) { final ManifestTokenType manifestTokenType = detectLineEntry().orElse(null); + if (manifestTokenType == ManifestTokenType.CMS_BEGIN) { + return; + } if (manifestTokenType != null) { reportError(Messages.MANIFEST_INVALID_NON_MANO_KEY, manifestTokenType.getToken()); continueToProcess = false; @@ -162,25 +164,35 @@ public class SOL004ManifestOnboarding extends AbstractOnboardingManifest { */ private void readCmsSignature() { if (cmsSignature != null) { - reportError(Messages.MANIFEST_DUPLICATED_CMS_SIGNATURE); + reportError(Messages.MANIFEST_SIGNATURE_DUPLICATED); continueToProcess = false; return; } + final StringBuilder cmsSignatureBuilder = new StringBuilder(); + + cmsSignatureBuilder.append(currentLine).append("\n"); Optional currentLine = readNextNonEmptyLine(); if(!getCurrentLine().isPresent()) { return; } - StringBuilder stringBuilder = new StringBuilder(); - while (currentLine.isPresent() && detectLineEntry().orElse(null) != ManifestTokenType.CMS_END) { - stringBuilder.append(currentLine.get()); - stringBuilder.append("\n"); + while (currentLine.isPresent()) { + if (detectLineEntry().orElse(null) == ManifestTokenType.CMS_END) { + cmsSignatureBuilder.append(currentLine.get()); + break; + } + cmsSignatureBuilder.append(currentLine.get()).append("\n"); currentLine = readNextNonEmptyLine(); } if (currentLine.isPresent()) { - cmsSignature = stringBuilder.toString(); + cmsSignature = cmsSignatureBuilder.toString(); readNextNonEmptyLine(); } + + if (getCurrentLine().isPresent()) { + reportError(Messages.MANIFEST_SIGNATURE_LAST_ENTRY); + continueToProcess = false; + } } /** diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboardingTest.java b/openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboardingTest.java index 7cb1511a32..d582163774 100644 --- a/openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboardingTest.java +++ b/openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboardingTest.java @@ -28,6 +28,7 @@ import static org.junit.Assert.assertThat; import com.google.common.collect.ImmutableMap; import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; @@ -56,7 +57,7 @@ public class SOL004ManifestOnboardingTest { try (final InputStream manifestAsStream = getClass().getResourceAsStream("/vspmanager.csar/manifest/ValidTosca.mf")) { manifest.parse(manifestAsStream); - assertValidManifest(4, 5, Collections.emptyMap(), ResourceTypeEnum.VF); + assertValidManifest(4, 5, Collections.emptyMap(), ResourceTypeEnum.VF, false); } } @@ -104,7 +105,7 @@ public class SOL004ManifestOnboardingTest { .getResourceAsStream("/vspmanager.csar/manifest/ValidNonManoTosca.mf")) { manifest.parse(manifestAsStream); assertValidManifest(4, 5, - ImmutableMap.of("foo_bar", 3, "prv.happy-nfv.cool", 3), ResourceTypeEnum.VF); + ImmutableMap.of("foo_bar", 3, "prv.happy-nfv.cool", 3), ResourceTypeEnum.VF, false); } } @@ -154,7 +155,7 @@ public class SOL004ManifestOnboardingTest { try (final InputStream manifestAsStream = getClass() .getResourceAsStream("/vspmanager.csar/manifest/valid/signed.mf")) { manifest.parse(manifestAsStream); - assertValidManifest(4, 3, Collections.emptyMap(), ResourceTypeEnum.VF); + assertValidManifest(4, 3, Collections.emptyMap(), ResourceTypeEnum.VF, true); } } @@ -163,7 +164,7 @@ public class SOL004ManifestOnboardingTest { try (final InputStream manifestAsStream = getClass() .getResourceAsStream("/vspmanager.csar/manifest/valid/signed-with-non-mano.mf")) { manifest.parse(manifestAsStream); - assertValidManifest(4, 3, ImmutableMap.of("foo_bar", 3), ResourceTypeEnum.VF); + assertValidManifest(4, 3, ImmutableMap.of("foo_bar", 3), ResourceTypeEnum.VF, true); manifest.getType().ifPresent(typeEnum -> assertSame(typeEnum, ResourceTypeEnum.VF)); } } @@ -173,7 +174,7 @@ public class SOL004ManifestOnboardingTest { try (final InputStream manifestAsStream = getClass() .getResourceAsStream("/vspmanager.csar/manifest/valid/metadata-pnfd.mf")) { manifest.parse(manifestAsStream); - assertValidManifest(4, 3, new HashMap<>(), ResourceTypeEnum.PNF); + assertValidManifest(4, 3, new HashMap<>(), ResourceTypeEnum.PNF, true); } } @@ -338,18 +339,23 @@ public class SOL004ManifestOnboardingTest { } @Test - public void testManifestWithDuplicatedCmsSignature() throws IOException { + public void testManifestWithDuplicatedCmsSignature() + throws IOException, NoSuchFieldException, IllegalAccessException { try (final InputStream manifestAsStream = - getClass().getResourceAsStream("/vspmanager.csar/manifest/invalid/double-signed.mf")) { + getClass().getResourceAsStream("/vspmanager.csar/manifest/valid/signed.mf")) { + //forcing an existing signature + final Field cmsSignatureField = AbstractOnboardingManifest.class.getDeclaredField("cmsSignature"); + cmsSignatureField.setAccessible(true); + cmsSignatureField.set(manifest, "any value"); manifest.parse(manifestAsStream); + final List expectedErrorList = new ArrayList<>(); expectedErrorList - .add(buildErrorMessage(26, "-----BEGIN CMS-----", Messages.MANIFEST_DUPLICATED_CMS_SIGNATURE)); + .add(buildErrorMessage(18, "-----BEGIN CMS-----", Messages.MANIFEST_SIGNATURE_DUPLICATED)); assertInvalidManifest(expectedErrorList); } } - @Test public void testGetEntry() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { final Method getEntryMethod = AbstractOnboardingManifest.class.getDeclaredMethod("readEntryName", String.class); @@ -408,7 +414,7 @@ public class SOL004ManifestOnboardingTest { private void assertValidManifest(final int expectedMetadataSize, final int expectedSourcesSize, final Map expectedNonManoKeySize, - final ResourceTypeEnum resourceType) { + final ResourceTypeEnum resourceType, final boolean isSigned) { assertThat("Should have no errors", manifest.getErrors(), is(empty())); assertThat("Should be valid", manifest.isValid(), is(true)); assertThat("Metadata should have the expected size", @@ -425,6 +431,7 @@ public class SOL004ManifestOnboardingTest { } assertThat("Should have a type", manifest.getType().isPresent(), is(true)); assertThat("Type should be as expected", manifest.getType().get(), equalTo(resourceType)); + assertThat("Signature status should be as expected", manifest.isSigned(), is(isSigned)); } private void assertInvalidManifest(final List expectedErrorList) { diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/double-signed.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/double-signed.mf deleted file mode 100644 index 88098a1006..0000000000 --- a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/double-signed.mf +++ /dev/null @@ -1,35 +0,0 @@ -metadata: - vnf_product_name: vPP - vnf_provider_id: Ericsson - vnf_package_version: R24A583 - vnf_release_date_time: 2019-08-29T22:17:39.275281 - -Source: scripts/userdata.file -Algorithm: md5 -Hash: 3b119b37da5b76ec7c933168b21cedd8 - ------BEGIN CMS----- -MIIBcwYJKoZIhvcNAQcCoIIBZDCCAWACAQMxDTALBglghkgBZQMEAgEwCwYJKoZI -hvcNAQcBMYIBPTCCATkCAQOAFGOGMKMvLSRzUBjkgZipSoZm1U/UMAsGCWCGSAFl -AwQCATANBgkqhkiG9w0BAQEFAASCAQBNHXz1p5NBM9Nlvp8RPoVjszzh9UfQ/OCp -mB926MTLexWOiawjPRKuoiXn4y4dQFZBXauunCOyXYfPASUMFnhL/7gvhajPH25/ -MwEyEsUqsCyJ63tAeYxZAqTZWA2pZi9ejCPoRnt6xl7EhEyogXiSBgc2P89hxhe6 -0/MP6Mtw9D8Ks7M1LxH6ntxGApPTNRlmMtQkrx/ZUtAcKKZJoNpofzdmd+O60PMT -igNsuwzMNy5LfSjvp8xgWoxhWr4/zLRIZ5F5Z5qhz7lia9xDSGYMfPitDCVqI9XE -O58S/FoHu+z3Tig7vauTFFbiJjIu9SkG0c33ayEUCKejuVQPjuY9 ------END CMS----- - -Source: scripts/userdata.file.sm -Algorithm: md5 -Hash: 3b119b37da5b76ec7c933168b21cedd7 - ------BEGIN CMS----- -MIIBcwYJKoZIhvcNAQcCoIIBZDCCAWACAQMxDTALBglghkgBZQMEAgEwCwYJKoZI -hvcNAQcBMYIBPTCCATkCAQOAFGOGMKMvLSRzUBjkgZipSoZm1U/UMAsGCWCGSAFl -AwQCATANBgkqhkiG9w0BAQEFAASCAQBNHXz1p5NBM9Nlvp8RPoVjszzh9UfQ/OCp -mB926MTLexWOiawjPRKuoiXn4y4dQFZBXauunCOyXYfPASUMFnhL/7gvhajPH25/ -MwEyEsUqsCyJ63tAeYxZAqTZWA2pZi9ejCPoRnt6xl7EhEyogXiSBgc2P89hxhe6 -0/MP6Mtw9D8Ks7M1LxH6ntxGApPTNRlmMtQkrx/ZUtAcKKZJoNpofzdmd+O60PMT -igNsuwzMNy5LfSjvp8xgWoxhWr4/zLRIZ5F5Z5qhz7lia9xDSGYMfPitDCVqI9XE -O58S/FoHu+z3Tig7vauTFFbiJjIu9SkG0c33ayEUCKejuVQPjuY9 ------END CMS----- diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/valid/signed-with-non-mano.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/valid/signed-with-non-mano.mf index dee6384892..d6669bcef9 100644 --- a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/valid/signed-with-non-mano.mf +++ b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/valid/signed-with-non-mano.mf @@ -12,6 +12,12 @@ Hash: 3b119b37da5b76ec7c933168b21cedd8 Source: scripts/userdata.file.sm +non_mano_artifact_sets: + foo_bar: + Source: foobar/foo/foo.yaml + Source: foobar/foo/foo.script + Source: foobar/bar/descriptor.xml + -----BEGIN CMS----- MIIBcwYJKoZIhvcNAQcCoIIBZDCCAWACAQMxDTALBglghkgBZQMEAgEwCwYJKoZI hvcNAQcBMYIBPTCCATkCAQOAFGOGMKMvLSRzUBjkgZipSoZm1U/UMAsGCWCGSAFl @@ -22,9 +28,3 @@ MwEyEsUqsCyJ63tAeYxZAqTZWA2pZi9ejCPoRnt6xl7EhEyogXiSBgc2P89hxhe6 igNsuwzMNy5LfSjvp8xgWoxhWr4/zLRIZ5F5Z5qhz7lia9xDSGYMfPitDCVqI9XE O58S/FoHu+z3Tig7vauTFFbiJjIu9SkG0c33ayEUCKejuVQPjuY9 -----END CMS----- - -non_mano_artifact_sets: - foo_bar: - Source: foobar/foo/foo.yaml - Source: foobar/foo/foo.script - Source: foobar/bar/descriptor.xml -- cgit 1.2.3-korg