mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 07:40:48 -08:00
fix(sbom): add buildInfo info as properties (#9683)
This commit is contained in:
@@ -47,6 +47,12 @@ const (
|
||||
PropertyLayerDigest = "LayerDigest"
|
||||
PropertyLayerDiffID = "LayerDiffID"
|
||||
|
||||
// Red Hat packages only.
|
||||
// A package can use multiple NVR + Arch content sets or fields.
|
||||
PropertyContentSet = "ContentSet"
|
||||
PropertyNVR = "NVR"
|
||||
PropertyArch = "Arch"
|
||||
|
||||
// Relationships
|
||||
RelationshipDescribes RelationshipType = "describes"
|
||||
RelationshipContains RelationshipType = "contains"
|
||||
|
||||
@@ -201,30 +201,8 @@ func (m *Decoder) decodePackage(ctx context.Context, c *core.Component) (*ftypes
|
||||
pkg.Name = m.pkgName(pkg, c)
|
||||
pkg.ID = dependency.ID(p.LangType(), pkg.Name, p.Version) // Re-generate ID with the updated name
|
||||
|
||||
var err error
|
||||
for _, prop := range c.Properties {
|
||||
switch prop.Name {
|
||||
case core.PropertyPkgID:
|
||||
pkg.ID = prop.Value
|
||||
case core.PropertyFilePath:
|
||||
pkg.FilePath = prop.Value
|
||||
case core.PropertySrcName:
|
||||
pkg.SrcName = prop.Value
|
||||
case core.PropertySrcVersion:
|
||||
pkg.SrcVersion = prop.Value
|
||||
case core.PropertySrcRelease:
|
||||
pkg.SrcRelease = prop.Value
|
||||
case core.PropertySrcEpoch:
|
||||
if pkg.SrcEpoch, err = strconv.Atoi(prop.Value); err != nil {
|
||||
return nil, xerrors.Errorf("invalid src epoch: %w", err)
|
||||
}
|
||||
case core.PropertyModularitylabel:
|
||||
pkg.Modularitylabel = prop.Value
|
||||
case core.PropertyLayerDigest:
|
||||
pkg.Layer.Digest = prop.Value
|
||||
case core.PropertyLayerDiffID:
|
||||
pkg.Layer.DiffID = prop.Value
|
||||
}
|
||||
if err := fillPkgFieldsFromComponentProps(c.Properties, pkg); err != nil {
|
||||
return nil, xerrors.Errorf("failed to fill package properties: %w", err)
|
||||
}
|
||||
|
||||
pkg.Identifier.BOMRef = c.PkgIdentifier.BOMRef
|
||||
@@ -413,3 +391,43 @@ func (m *Decoder) addOrphanPkgs(sbom *types.SBOM) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fillPkgFieldsFromComponentProps(props []core.Property, pkg *ftypes.Package) error {
|
||||
buildInfo := &ftypes.BuildInfo{}
|
||||
var err error
|
||||
for _, prop := range props {
|
||||
switch prop.Name {
|
||||
case core.PropertyPkgID:
|
||||
pkg.ID = prop.Value
|
||||
case core.PropertyFilePath:
|
||||
pkg.FilePath = prop.Value
|
||||
case core.PropertySrcName:
|
||||
pkg.SrcName = prop.Value
|
||||
case core.PropertySrcVersion:
|
||||
pkg.SrcVersion = prop.Value
|
||||
case core.PropertySrcRelease:
|
||||
pkg.SrcRelease = prop.Value
|
||||
case core.PropertySrcEpoch:
|
||||
if pkg.SrcEpoch, err = strconv.Atoi(prop.Value); err != nil {
|
||||
return xerrors.Errorf("invalid src epoch: %w", err)
|
||||
}
|
||||
case core.PropertyModularitylabel:
|
||||
pkg.Modularitylabel = prop.Value
|
||||
case core.PropertyLayerDigest:
|
||||
pkg.Layer.Digest = prop.Value
|
||||
case core.PropertyLayerDiffID:
|
||||
pkg.Layer.DiffID = prop.Value
|
||||
case core.PropertyContentSet:
|
||||
buildInfo.ContentSets = append(buildInfo.ContentSets, prop.Value)
|
||||
case core.PropertyNVR:
|
||||
buildInfo.Nvr = prop.Value
|
||||
case core.PropertyArch:
|
||||
buildInfo.Arch = prop.Value
|
||||
}
|
||||
}
|
||||
|
||||
if len(buildInfo.ContentSets) > 0 || buildInfo.Nvr != "" {
|
||||
pkg.BuildInfo = buildInfo
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -85,6 +85,24 @@ var (
|
||||
Version: "2.0.0",
|
||||
},
|
||||
},
|
||||
Properties: core.Properties{
|
||||
{
|
||||
Name: core.PropertyContentSet,
|
||||
Value: "rhel-9-for-aarch64-appstream-rpms",
|
||||
},
|
||||
{
|
||||
Name: core.PropertyContentSet,
|
||||
Value: "rhel-9-for-aarch64-appstream-source-rpms",
|
||||
},
|
||||
{
|
||||
Name: core.PropertySrcName,
|
||||
Value: "rpm-package",
|
||||
},
|
||||
{
|
||||
Name: core.PropertySrcVersion,
|
||||
Value: "2.0.0",
|
||||
},
|
||||
},
|
||||
Licenses: []string{"GPL-2.0"},
|
||||
}
|
||||
|
||||
@@ -233,6 +251,47 @@ func TestDecoder_Decode_OSPackages(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "rpm package",
|
||||
setupBOM: func() *core.BOM {
|
||||
bom := core.NewBOM(core.Options{})
|
||||
bom.SerialNumber = "test-multiple-os-types"
|
||||
bom.Version = 1
|
||||
|
||||
// Add RPM package
|
||||
bom.AddComponent(rpmTestComponent)
|
||||
|
||||
return bom
|
||||
},
|
||||
wantSBOM: types.SBOM{
|
||||
Metadata: types.Metadata{
|
||||
OS: nil, // No OS detected
|
||||
},
|
||||
Packages: []ftypes.PackageInfo{
|
||||
{
|
||||
Packages: ftypes.Packages{
|
||||
{
|
||||
ID: "rpm-package@2.0.0",
|
||||
Name: "rpm-package",
|
||||
Version: "2.0.0",
|
||||
SrcName: "rpm-package",
|
||||
SrcVersion: "2.0.0",
|
||||
Licenses: []string{"GPL-2.0"},
|
||||
Identifier: ftypes.PkgIdentifier{
|
||||
PURL: rpmTestComponent.PkgIdentifier.PURL,
|
||||
},
|
||||
BuildInfo: &ftypes.BuildInfo{
|
||||
ContentSets: []string{
|
||||
"rhel-9-for-aarch64-appstream-rpms",
|
||||
"rhel-9-for-aarch64-appstream-source-rpms",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple OS package types should return error",
|
||||
setupBOM: func() *core.BOM {
|
||||
|
||||
@@ -423,6 +423,29 @@ func (*Encoder) component(result types.Result, pkg ftypes.Package) *core.Compone
|
||||
},
|
||||
}
|
||||
|
||||
// Fill Red Hat specific properties
|
||||
if pkg.BuildInfo != nil {
|
||||
for _, cs := range pkg.BuildInfo.ContentSets {
|
||||
properties = append(properties, core.Property{
|
||||
Name: core.PropertyContentSet,
|
||||
Value: cs,
|
||||
})
|
||||
}
|
||||
|
||||
if pkg.BuildInfo.Nvr != "" {
|
||||
properties = append(properties, core.Property{
|
||||
Name: core.PropertyNVR,
|
||||
Value: pkg.BuildInfo.Nvr,
|
||||
})
|
||||
}
|
||||
if pkg.BuildInfo.Arch != "" {
|
||||
properties = append(properties, core.Property{
|
||||
Name: core.PropertyArch,
|
||||
Value: pkg.BuildInfo.Arch,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var files []core.File
|
||||
if pkg.FilePath != "" || pkg.Digest != "" {
|
||||
files = append(files, core.File{
|
||||
|
||||
@@ -589,6 +589,207 @@ func TestEncoder_Encode(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Red Hat container image",
|
||||
report: types.Report{
|
||||
SchemaVersion: 2,
|
||||
ArtifactName: "redhat/ubi9-minimal",
|
||||
ArtifactType: ftypes.TypeContainerImage,
|
||||
Metadata: types.Metadata{
|
||||
OS: &ftypes.OS{
|
||||
Family: ftypes.RedHat,
|
||||
Name: "9.5",
|
||||
},
|
||||
RepoTags: []string{
|
||||
"redhat/ubi9:latest",
|
||||
},
|
||||
RepoDigests: []string{
|
||||
"redhat/ubi9-minimal@sha256:e1c4703364c5cb58f5462575dc90345bcd934ddc45e6c32f9c162f2b5617681c",
|
||||
},
|
||||
ImageConfig: v1.ConfigFile{
|
||||
Config: v1.Config{
|
||||
Labels: map[string]string{
|
||||
"vendor": "aquasecurity",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Results: []types.Result{
|
||||
{
|
||||
Target: "redhat/ubi9-minimal (redhat 9.5)",
|
||||
Type: ftypes.RedHat,
|
||||
Class: types.ClassOSPkg,
|
||||
Packages: []ftypes.Package{
|
||||
{
|
||||
ID: "glibc@2.34-125.el9_5.8.aarch64",
|
||||
Name: "glibc",
|
||||
Version: "2.34",
|
||||
Release: "125.el9_5.8.aarch64",
|
||||
Arch: "aarch64",
|
||||
SrcName: "glibc",
|
||||
SrcVersion: "2.34",
|
||||
SrcRelease: "125.el9_5.8",
|
||||
Maintainer: "Red Hat, Inc.",
|
||||
BuildInfo: &ftypes.BuildInfo{
|
||||
ContentSets: []string{
|
||||
"rhel-9-for-aarch64-appstream-rpms",
|
||||
"rhel-9-for-aarch64-appstream-source-rpms",
|
||||
},
|
||||
},
|
||||
Identifier: ftypes.PkgIdentifier{
|
||||
UID: "2acbd589f06ebbb8",
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: packageurl.TypeRPM,
|
||||
Name: "glibc",
|
||||
Version: "2.34-125.el9_5.8",
|
||||
Qualifiers: packageurl.Qualifiers{
|
||||
{
|
||||
Key: "arch",
|
||||
Value: "aarch64",
|
||||
},
|
||||
{
|
||||
Key: "distro",
|
||||
Value: "redhat-9.5",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantComponents: map[uuid.UUID]*core.Component{
|
||||
uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000001"): {
|
||||
Type: core.TypeContainerImage,
|
||||
Name: "redhat/ubi9-minimal",
|
||||
Root: true,
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: packageurl.TypeOCI,
|
||||
Name: "ubi9-minimal",
|
||||
Version: "sha256:e1c4703364c5cb58f5462575dc90345bcd934ddc45e6c32f9c162f2b5617681c",
|
||||
Qualifiers: packageurl.Qualifiers{
|
||||
{
|
||||
Key: "repository_url",
|
||||
Value: "index.docker.io/redhat/ubi9-minimal",
|
||||
},
|
||||
},
|
||||
},
|
||||
BOMRef: "pkg:oci/ubi9-minimal@sha256%3Ae1c4703364c5cb58f5462575dc90345bcd934ddc45e6c32f9c162f2b5617681c?repository_url=index.docker.io%2Fredhat%2Fubi9-minimal",
|
||||
},
|
||||
Properties: []core.Property{
|
||||
{
|
||||
Name: "Labels:vendor",
|
||||
Value: "aquasecurity",
|
||||
},
|
||||
{
|
||||
Name: core.PropertyRepoDigest,
|
||||
Value: "redhat/ubi9-minimal@sha256:e1c4703364c5cb58f5462575dc90345bcd934ddc45e6c32f9c162f2b5617681c",
|
||||
},
|
||||
{
|
||||
Name: core.PropertyRepoTag,
|
||||
Value: "redhat/ubi9:latest",
|
||||
},
|
||||
{
|
||||
Name: core.PropertySchemaVersion,
|
||||
Value: "2",
|
||||
},
|
||||
},
|
||||
},
|
||||
uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000002"): {
|
||||
Type: core.TypeOS,
|
||||
Name: "redhat",
|
||||
Version: "9.5",
|
||||
Properties: []core.Property{
|
||||
{
|
||||
Name: core.PropertyClass,
|
||||
Value: "os-pkgs",
|
||||
},
|
||||
{
|
||||
Name: core.PropertyType,
|
||||
Value: "redhat",
|
||||
},
|
||||
},
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
BOMRef: "3ff14136-e09f-4df9-80ea-000000000002",
|
||||
},
|
||||
},
|
||||
uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000003"): {
|
||||
Type: core.TypeLibrary,
|
||||
Name: "glibc",
|
||||
Version: "2.34-125.el9_5.8",
|
||||
SrcName: "glibc",
|
||||
SrcVersion: "2.34-125.el9_5.8",
|
||||
Supplier: "Red Hat, Inc.",
|
||||
Properties: []core.Property{
|
||||
{
|
||||
Name: core.PropertyContentSet,
|
||||
Value: "rhel-9-for-aarch64-appstream-rpms",
|
||||
},
|
||||
{
|
||||
Name: core.PropertyContentSet,
|
||||
Value: "rhel-9-for-aarch64-appstream-source-rpms",
|
||||
},
|
||||
{
|
||||
Name: core.PropertyPkgID,
|
||||
Value: "glibc@2.34-125.el9_5.8.aarch64",
|
||||
},
|
||||
{
|
||||
Name: core.PropertyPkgType,
|
||||
Value: "redhat",
|
||||
},
|
||||
{
|
||||
Name: core.PropertySrcName,
|
||||
Value: "glibc",
|
||||
},
|
||||
{
|
||||
Name: core.PropertySrcRelease,
|
||||
Value: "125.el9_5.8",
|
||||
},
|
||||
{
|
||||
Name: core.PropertySrcVersion,
|
||||
Value: "2.34",
|
||||
},
|
||||
},
|
||||
PkgIdentifier: ftypes.PkgIdentifier{
|
||||
UID: "2acbd589f06ebbb8",
|
||||
PURL: &packageurl.PackageURL{
|
||||
Type: packageurl.TypeRPM,
|
||||
Name: "glibc",
|
||||
Version: "2.34-125.el9_5.8",
|
||||
Qualifiers: packageurl.Qualifiers{
|
||||
{
|
||||
Key: "arch",
|
||||
Value: "aarch64",
|
||||
},
|
||||
{
|
||||
Key: "distro",
|
||||
Value: "redhat-9.5",
|
||||
},
|
||||
},
|
||||
},
|
||||
BOMRef: "pkg:rpm/glibc@2.34-125.el9_5.8?arch=aarch64&distro=redhat-9.5",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantRels: map[uuid.UUID][]core.Relationship{
|
||||
uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000001"): {
|
||||
{
|
||||
Dependency: uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000002"),
|
||||
Type: core.RelationshipContains,
|
||||
},
|
||||
},
|
||||
uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000002"): {
|
||||
{
|
||||
Dependency: uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000003"),
|
||||
Type: core.RelationshipContains,
|
||||
},
|
||||
},
|
||||
uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000003"): nil,
|
||||
},
|
||||
wantVulns: make(map[uuid.UUID][]core.Vulnerability),
|
||||
},
|
||||
{
|
||||
name: "root package",
|
||||
report: types.Report{
|
||||
|
||||
Reference in New Issue
Block a user