github.com/anchore/syft@v1.38.2/syft/pkg/cataloger/internal/binutils/classifier_package.go (about)

     1  package binutils
     2  
     3  import (
     4  	"bytes"
     5  	"reflect"
     6  	"text/template"
     7  
     8  	"github.com/anchore/packageurl-go"
     9  	"github.com/anchore/syft/internal/log"
    10  	"github.com/anchore/syft/syft/cpe"
    11  	"github.com/anchore/syft/syft/file"
    12  	"github.com/anchore/syft/syft/pkg"
    13  )
    14  
    15  var emptyPURL = packageurl.PackageURL{}
    16  
    17  func NewClassifierPackage(classifier Classifier, location file.Location, matchMetadata map[string]string, catalogerName string) *pkg.Package {
    18  	version, ok := matchMetadata["version"]
    19  	if !ok {
    20  		return nil
    21  	}
    22  
    23  	update := matchMetadata["update"]
    24  
    25  	var cpes []cpe.CPE
    26  	for _, c := range classifier.CPEs {
    27  		c.Attributes.Version = templatedUpdate(c.Attributes.Version, matchMetadata, version)
    28  		c.Attributes.Update = templatedUpdate(c.Attributes.Update, matchMetadata, update)
    29  		cpes = append(cpes, c)
    30  	}
    31  
    32  	p := pkg.Package{
    33  		Name:    classifier.Package,
    34  		Version: version,
    35  		Locations: file.NewLocationSet(
    36  			location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
    37  		),
    38  		Type:    pkg.BinaryPkg,
    39  		CPEs:    cpes,
    40  		FoundBy: catalogerName,
    41  		Metadata: pkg.BinarySignature{
    42  			Matches: []pkg.ClassifierMatch{
    43  				{
    44  					Classifier: classifier.Class,
    45  					Location:   location,
    46  				},
    47  			},
    48  		},
    49  	}
    50  
    51  	if !reflect.DeepEqual(classifier.PURL, emptyPURL) {
    52  		purl := classifier.PURL
    53  		purl.Version = version
    54  		p.PURL = purl.ToString()
    55  	}
    56  
    57  	p.SetID()
    58  
    59  	return &p
    60  }
    61  
    62  func templatedUpdate(providedValue string, matchMetadata map[string]string, defaultValue string) string {
    63  	// if no template provided, just use the value directly
    64  	if providedValue == "" {
    65  		return defaultValue
    66  	}
    67  	// support templated updates
    68  	t, err := template.New("").Option("missingkey=zero").Parse(providedValue)
    69  	if err != nil {
    70  		log.Debugf("unable to parse classifier template=%q : %w", providedValue, err)
    71  	} else {
    72  		update := bytes.Buffer{}
    73  		err = t.Execute(&update, matchMetadata)
    74  		if err != nil {
    75  			log.Debugf("unable to render template: %w", err)
    76  		} else {
    77  			// only use the template result if it's non-empty
    78  			providedValue = update.String()
    79  			if providedValue != "" {
    80  				return providedValue
    81  			}
    82  		}
    83  	}
    84  	return defaultValue
    85  }