Skip to content

Commit

Permalink
more CPE fields and output to PKGINFO
Browse files Browse the repository at this point in the history
Signed-off-by: Dan Luhring <[email protected]>
  • Loading branch information
luhring committed Jan 31, 2025
1 parent 5629b3b commit 90a1c28
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 8 deletions.
12 changes: 12 additions & 0 deletions pkg/build/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ type PackageBuild struct {
Description string
URL string
Commit string
CPE string
}

func pkgFromSub(sub *config.Subpackage) *config.Package {
Expand All @@ -93,6 +94,13 @@ func pkgFromSub(sub *config.Subpackage) *config.Package {
}

func (b *Build) Emit(ctx context.Context, pkg *config.Package) error {
log := clog.FromContext(ctx)

renderedCPE, err := pkg.CPEString()
if err != nil {
log.Infof("unable to generate CPE string for package %s: %v", pkg.Name, err)
}

pc := PackageBuild{
Build: b,
Origin: &b.Configuration.Package,
Expand All @@ -106,6 +114,7 @@ func (b *Build) Emit(ctx context.Context, pkg *config.Package) error {
Description: pkg.Description,
URL: pkg.URL,
Commit: pkg.Commit,
CPE: renderedCPE,
}

if !b.StripOriginName {
Expand Down Expand Up @@ -181,6 +190,9 @@ replaces_priority = {{ .Dependencies.ReplacesPriority }}
{{- if .Scriptlets}}{{ if .Scriptlets.Trigger.Paths }}
triggers = {{ range $item := .Scriptlets.Trigger.Paths }}{{ $item }} {{ end }}
{{- end }}{{ end }}
{{- if .CPE }}
# cpe = {{ .CPE }}
{{- end }}
datahash = {{.DataHash}}
`

Expand Down
83 changes: 75 additions & 8 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,24 @@ type Package struct {
// CPE stores values used to produce a CPE to describe the package, suitable for
// matching against NVD records.
//
// Based on the spec found at
// https://nvlpubs.nist.gov/nistpubs/Legacy/IR/nistir7695.pdf.
//
// For Melange, the "part" attribute should always be interpreted as "a" (for
// "application").
// "application") unless otherwise specified.
//
// The "Version" and "Update" fields have been intentionally left out of the CPE
// struct to avoid confusion with the version information of the package itself.
type CPE struct {
Vendor string
Product string
Part string `json:"part,omitempty" yaml:"part,omitempty"`
Vendor string `json:"vendor,omitempty" yaml:"vendor,omitempty"`
Product string `json:"product,omitempty" yaml:"product,omitempty"`
Edition string `json:"edition,omitempty" yaml:"edition,omitempty"`
Language string `json:"language,omitempty" yaml:"language,omitempty"`
SWEdition string `json:"sw_edition,omitempty" yaml:"sw_edition,omitempty"`
TargetSW string `json:"target_sw,omitempty" yaml:"target_sw,omitempty"`
TargetHW string `json:"target_hw,omitempty" yaml:"target_hw,omitempty"`
Other string `json:"other,omitempty" yaml:"other,omitempty"`
}

type Resources struct {
Expand All @@ -145,13 +158,67 @@ type Resources struct {

// CPEString returns the CPE string for the package, suitable for matching
// against NVD records.
func (p Package) CPEString() string {
func (p Package) CPEString() (string, error) {
const anyValue = "*"

part := anyValue
if p.CPE.Part != "" {
part = p.CPE.Part
}
vendor := anyValue
if p.CPE.Vendor != "" {
vendor = p.CPE.Vendor
}
product := anyValue
if p.CPE.Product != "" {
product = p.CPE.Product
}
edition := anyValue
if p.CPE.Edition != "" {
edition = p.CPE.Edition
}
language := anyValue
if p.CPE.Language != "" {
language = p.CPE.Language
}
swEdition := anyValue
if p.CPE.SWEdition != "" {
swEdition = p.CPE.SWEdition
}
targetSW := anyValue
if p.CPE.TargetSW != "" {
targetSW = p.CPE.TargetSW
}
targetHW := anyValue
if p.CPE.TargetHW != "" {
targetHW = p.CPE.TargetHW
}
other := anyValue
if p.CPE.Other != "" {
other = p.CPE.Other
}

// Last-mile validation to avoid headaches downstream of this.
if vendor == anyValue {
return "", fmt.Errorf("vendor value must be exactly specified")
}
if product == anyValue {
return "", fmt.Errorf("product value must be exactly specified")
}

return fmt.Sprintf(
"cpe:2.3:a:%s:%s:%s:*:*:*:*:*:*:*:*",
p.CPE.Vendor,
p.CPE.Product,
"cpe:2.3:%s:%s:%s:%s:*:%s:%s:%s:%s:%s:%s",
part,
vendor,
product,
p.Version,
)
edition,
language,
swEdition,
targetSW,
targetHW,
other,
), nil
}

// PackageURL returns the package URL ("purl") for the APK (origin) package.
Expand Down

0 comments on commit 90a1c28

Please sign in to comment.