Repository: sonatype-nexus-community/nancy
Pull request #141 (2020-05-01 16:55:50)

Use v for Version if it's IQ, none if it's OSS Index
Basically, OSS Index and IQ keep track of versions very differently. OSS Index has versions without the `v` before it, and IQ has it with `v` before it. This makes hybrid approaches slightly interesting.

This pull request makes the following changes:
* Use the method to get purls that OSS Index uses, before we call IQ
* In the CycloneDX generator, if we notice a `v` is missing before a version, add it!
* Updates test for new behavior

cc @bhamail / @DarthHater



Patch:
diff --git a/cyclonedx/cyclonedx.go b/cyclonedx/cyclonedx.go
index c7d58c0..2c13659 100644
--- a/cyclonedx/cyclonedx.go
+++ b/cyclonedx/cyclonedx.go
@@ -19,6 +19,8 @@ package cyclonedx
 
 import (
 	"encoding/xml"
+	"fmt"
+	"strings"
 
 	"github.com/sonatype-nexus-community/nancy/customerrors"
 
@@ -98,6 +100,11 @@ func processPurlsIntoSBOMSchema1_1(results []types.Coordinate) string {
 			return ""
 		}
 
+		// IQ requires a v before versions, so add one if it doesn't exist
+		if !strings.HasPrefix(purl.Version, "v") {
+			purl.Version = fmt.Sprintf("v%s", purl.Version)
+		}
+
 		component := types.Component{
 			Type:    "library",
 			BomRef:  purl.String(),
diff --git a/main.go b/main.go
index d884fab..fca3436 100644
--- a/main.go
+++ b/main.go
@@ -293,7 +293,7 @@ func doStdInAndParseForIQ(config configuration.IqConfiguration) (err error) {
 		"projectList": mod.ProjectList,
 	}).Debug("Obtained project list")
 
-	var purls = mod.ExtractPurlsFromManifestForIQ()
+	var purls = mod.ExtractPurlsFromManifest()
 	LogLady.WithFields(logrus.Fields{
 		"purls": purls,
 	}).Debug("Extracted purls")


Test patch:
diff --git a/cyclonedx/cyclonedx_test.go b/cyclonedx/cyclonedx_test.go
index 0e2b3ee..949b8c5 100644
--- a/cyclonedx/cyclonedx_test.go
+++ b/cyclonedx/cyclonedx_test.go
@@ -103,10 +103,14 @@ func TestCreateSBOMFromSHA1s(t *testing.T) {
 func TestProcessPurlsIntoSBOM(t *testing.T) {
 	var results []types.Coordinate
 	crypto := types.Coordinate{
-		Coordinates:     "pkg:golang/golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2",
-		Reference:       "https://ossindex.sonatype.org/component/pkg:golang/golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2",
+		Coordinates:     "pkg:golang/golang.org/x/crypto@0.0.0-20190308221718-c2843e01d9a2",
+		Reference:       "https://ossindex.sonatype.org/component/pkg:golang/golang.org/x/crypto@0.0.0-20190308221718-c2843e01d9a2",
 		Vulnerabilities: []types.Vulnerability{},
 	}
+
+	expectedPurl := []string{"pkg:golang/golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2", "pkg:golang/github.com/go-yaml/yaml@v2.2.2"}
+	expectedVersion := []string{"v0.0.0-20190308221718-c2843e01d9a2", "v2.2.2"}
+
 	dec, _ := decimal.NewFromString("5.8")
 	crypto.Vulnerabilities = append(crypto.Vulnerabilities,
 		types.Vulnerability{
@@ -121,8 +125,8 @@ func TestProcessPurlsIntoSBOM(t *testing.T) {
 	results = append(results, crypto)
 
 	results = append(results, types.Coordinate{
-		Coordinates:     "pkg:golang/github.com/go-yaml/yaml@v2.2.2",
-		Reference:       "https://ossindex.sonatype.org/component/pkg:golang/github.com/go-yaml/yaml@v2.2.2",
+		Coordinates:     "pkg:golang/github.com/go-yaml/yaml@2.2.2",
+		Reference:       "https://ossindex.sonatype.org/component/pkg:golang/github.com/go-yaml/yaml@2.2.2",
 		Vulnerabilities: []types.Vulnerability{},
 	})
 	result := ProcessPurlsIntoSBOM(results)
@@ -142,19 +146,19 @@ func TestProcessPurlsIntoSBOM(t *testing.T) {
 		assert.Equal(t, component.Attr[0].Key, "type")
 		assert.Equal(t, component.Attr[0].Value, "library")
 		assert.Equal(t, component.Attr[1].Key, "bom-ref")
-		assert.Equal(t, component.Attr[1].Value, results[i].Coordinates)
+		assert.Equal(t, expectedPurl[i], component.Attr[1].Value)
 		name := component.SelectElement("name")
 		assert.Equal(t, name.Tag, "name")
 		assert.Equal(t, name.Text(), coordinate.Name)
 		version := component.SelectElement("version")
 		assert.Equal(t, version.Tag, "version")
-		assert.Equal(t, version.Text(), coordinate.Version)
+		assert.Equal(t, expectedVersion[i], version.Text())
 		hashes := component.SelectElement("hashes")
 		assert.Equal(t, hashes, nil)
 		purl := component.SelectElement("purl")
 		assert.Equal(t, purl.Tag, "purl")
-		assert.Equal(t, purl.Text(), coordinate.ToString())
-		if purl.Text() == "pkg:golang/golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2" {
+		assert.Equal(t, expectedPurl[i], purl.Text())
+		if purl.Text() == expectedPurl[i] {
 			vulnerabilities := component.SelectElement("vulnerabilities")
 			assert.Equal(t, vulnerabilities.Space, "v")
 			assert.Equal(t, vulnerabilities.Tag, "vulnerabilities")