mirror of
https://github.com/anchore/syft.git
synced 2025-11-18 00:43:20 +01:00
[CycloneDX] Add artifactID and groupID to the cycloneDX properties (support lower level struct as properties) (#758)
* [CycloneDX] Add artifactID and groupID to the cycloneDX properties Signed-off-by: Peter Balogh <p.balogh.sa@gmail.com> * update comment Signed-off-by: Peter Balogh <p.balogh.sa@gmail.com> * additional checks for value Signed-off-by: Peter Balogh <p.balogh.sa@gmail.com> * fill group filed with groupID in the case of Java Signed-off-by: Peter Balogh <p.balogh.sa@gmail.com> * fix linter warning Signed-off-by: Alex Goodman <alex.goodman@anchore.com> Co-authored-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
parent
6f0fad7ffd
commit
161fa7be4a
@ -9,6 +9,7 @@ func Component(p pkg.Package) cyclonedx.Component {
|
|||||||
return cyclonedx.Component{
|
return cyclonedx.Component{
|
||||||
Type: cyclonedx.ComponentTypeLibrary,
|
Type: cyclonedx.ComponentTypeLibrary,
|
||||||
Name: p.Name,
|
Name: p.Name,
|
||||||
|
Group: Group(p),
|
||||||
Version: p.Version,
|
Version: p.Version,
|
||||||
PackageURL: p.PURL,
|
PackageURL: p.PURL,
|
||||||
Licenses: Licenses(p),
|
Licenses: Licenses(p),
|
||||||
|
|||||||
12
internal/formats/common/cyclonedxhelpers/group.go
Normal file
12
internal/formats/common/cyclonedxhelpers/group.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package cyclonedxhelpers
|
||||||
|
|
||||||
|
import "github.com/anchore/syft/syft/pkg"
|
||||||
|
|
||||||
|
func Group(p pkg.Package) string {
|
||||||
|
if hasMetadata(p) {
|
||||||
|
if metadata, ok := p.Metadata.(pkg.JavaMetadata); ok && metadata.PomProperties != nil {
|
||||||
|
return metadata.PomProperties.GroupID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
52
internal/formats/common/cyclonedxhelpers/group_test.go
Normal file
52
internal/formats/common/cyclonedxhelpers/group_test.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package cyclonedxhelpers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGroup(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input pkg.Package
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no metadata",
|
||||||
|
input: pkg.Package{},
|
||||||
|
expected: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "metadata is not Java",
|
||||||
|
input: pkg.Package{
|
||||||
|
Metadata: pkg.NpmPackageJSONMetadata{},
|
||||||
|
},
|
||||||
|
expected: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "metadata is Java but pom properties is empty",
|
||||||
|
input: pkg.Package{
|
||||||
|
Metadata: pkg.JavaMetadata{},
|
||||||
|
},
|
||||||
|
expected: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "metadata is Java and contains pomProperties",
|
||||||
|
input: pkg.Package{
|
||||||
|
Metadata: pkg.JavaMetadata{
|
||||||
|
PomProperties: &pkg.PomProperties{
|
||||||
|
GroupID: "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: "test",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
assert.Equal(t, test.expected, Group(test.input))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -28,19 +28,24 @@ func Properties(p pkg.Package) *[]cyclonedx.Property {
|
|||||||
func getCycloneDXProperties(m interface{}) *[]cyclonedx.Property {
|
func getCycloneDXProperties(m interface{}) *[]cyclonedx.Property {
|
||||||
props := []cyclonedx.Property{}
|
props := []cyclonedx.Property{}
|
||||||
structValue := reflect.ValueOf(m)
|
structValue := reflect.ValueOf(m)
|
||||||
// we can only handle top level structs as interfaces for now
|
|
||||||
if structValue.Kind() != reflect.Struct {
|
if structValue.Kind() != reflect.Struct {
|
||||||
return &props
|
return &props
|
||||||
}
|
}
|
||||||
structType := structValue.Type()
|
structType := structValue.Type()
|
||||||
for i := 0; i < structValue.NumField(); i++ {
|
for i := 0; i < structValue.NumField(); i++ {
|
||||||
if name, value := getCycloneDXPropertyName(structType.Field(i)), getCycloneDXPropertyValue(structValue.Field(i)); name != "" && value != "" {
|
if name, value := getCycloneDXPropertyName(structType.Field(i)), getCycloneDXPropertyValue(structValue.Field(i)); name != "" && value != "" {
|
||||||
|
// In the case of the value is a struct and has cyclonedx tag with name "-"
|
||||||
|
// call the getCycloneDXProperties recursively.
|
||||||
|
if name == "-" && reflect.ValueOf(value).Kind() == reflect.Struct {
|
||||||
|
props = append(props, *getCycloneDXProperties(value)...)
|
||||||
|
} else if reflect.ValueOf(value).Kind() == reflect.String {
|
||||||
props = append(props, cyclonedx.Property{
|
props = append(props, cyclonedx.Property{
|
||||||
Name: name,
|
Name: name,
|
||||||
Value: value,
|
Value: fmt.Sprint(value),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return &props
|
return &props
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +56,7 @@ func getCycloneDXPropertyName(field reflect.StructField) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCycloneDXPropertyValue(field reflect.Value) string {
|
func getCycloneDXPropertyValue(field reflect.Value) interface{} {
|
||||||
if field.IsZero() {
|
if field.IsZero() {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -61,6 +66,11 @@ func getCycloneDXPropertyValue(field reflect.Value) string {
|
|||||||
return fmt.Sprint(field.Interface())
|
return fmt.Sprint(field.Interface())
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
|
case reflect.Struct:
|
||||||
|
if field.CanInterface() {
|
||||||
|
return field.Interface()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
return getCycloneDXPropertyValue(reflect.Indirect(field))
|
return getCycloneDXPropertyValue(reflect.Indirect(field))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ var JenkinsPluginPomPropertiesGroupIDs = []string{
|
|||||||
type JavaMetadata struct {
|
type JavaMetadata struct {
|
||||||
VirtualPath string `json:"virtualPath"`
|
VirtualPath string `json:"virtualPath"`
|
||||||
Manifest *JavaManifest `mapstructure:"Manifest" json:"manifest,omitempty"`
|
Manifest *JavaManifest `mapstructure:"Manifest" json:"manifest,omitempty"`
|
||||||
PomProperties *PomProperties `mapstructure:"PomProperties" json:"pomProperties,omitempty"`
|
PomProperties *PomProperties `mapstructure:"PomProperties" json:"pomProperties,omitempty" cyclonedx:"-"`
|
||||||
PomProject *PomProject `mapstructure:"PomProject" json:"pomProject,omitempty"`
|
PomProject *PomProject `mapstructure:"PomProject" json:"pomProject,omitempty"`
|
||||||
Parent *Package `hash:"ignore" json:"-"` // note: the parent cannot be included in the minimal definition of uniqueness since this field is not reproducible in an encode-decode cycle (is lossy).
|
Parent *Package `hash:"ignore" json:"-"` // note: the parent cannot be included in the minimal definition of uniqueness since this field is not reproducible in an encode-decode cycle (is lossy).
|
||||||
}
|
}
|
||||||
@ -32,8 +32,8 @@ type JavaMetadata struct {
|
|||||||
type PomProperties struct {
|
type PomProperties struct {
|
||||||
Path string `mapstructure:"path" json:"path"`
|
Path string `mapstructure:"path" json:"path"`
|
||||||
Name string `mapstructure:"name" json:"name"`
|
Name string `mapstructure:"name" json:"name"`
|
||||||
GroupID string `mapstructure:"groupId" json:"groupId"`
|
GroupID string `mapstructure:"groupId" json:"groupId" cyclonedx:"groupID"`
|
||||||
ArtifactID string `mapstructure:"artifactId" json:"artifactId"`
|
ArtifactID string `mapstructure:"artifactId" json:"artifactId" cyclonedx:"artifactID"`
|
||||||
Version string `mapstructure:"version" json:"version"`
|
Version string `mapstructure:"version" json:"version"`
|
||||||
Extra map[string]string `mapstructure:",remain" json:"extraFields"`
|
Extra map[string]string `mapstructure:",remain" json:"extraFields"`
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user