github.com/anchore/syft@v1.38.2/syft/pkg/cataloger/bitnami/package.go (about)

     1  package bitnami
     2  
     3  import (
     4  	"fmt"
     5  	"path"
     6  	"path/filepath"
     7  	"slices"
     8  	"strings"
     9  
    10  	"github.com/bitnami/go-version/pkg/version"
    11  
    12  	"github.com/anchore/packageurl-go"
    13  	"github.com/anchore/syft/syft/artifact"
    14  	"github.com/anchore/syft/syft/file"
    15  	"github.com/anchore/syft/syft/pkg"
    16  )
    17  
    18  func parseBitnamiPURL(p string) (*pkg.BitnamiSBOMEntry, error) {
    19  	purl, err := packageurl.FromString(p)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  
    24  	v, err := version.Parse(purl.Version)
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  
    29  	entry := pkg.BitnamiSBOMEntry{
    30  		Name:     purl.Name,
    31  		Version:  strings.TrimSuffix(v.String(), fmt.Sprintf("-%s", v.Revision().String())),
    32  		Revision: v.Revision().String(),
    33  	}
    34  
    35  	for _, q := range purl.Qualifiers {
    36  		switch q.Key {
    37  		case "arch":
    38  			entry.Architecture = q.Value
    39  		case "distro":
    40  			entry.Distro = q.Value
    41  		}
    42  	}
    43  
    44  	return &entry, nil
    45  }
    46  
    47  // packageFiles goes through the list of relationships and finds the files that
    48  // are owned by the given package
    49  func packageFiles(relationships []artifact.Relationship, p pkg.Package, baseDirectory string) []string {
    50  	var result []string
    51  	for _, r := range relationships {
    52  		if r.Type != artifact.ContainsRelationship {
    53  			continue
    54  		}
    55  
    56  		if from, ok := r.From.(pkg.Package); ok {
    57  			if from.PURL == p.PURL {
    58  				if to, ok := r.To.(pkg.Package); ok {
    59  					result = append(result, packageFiles(relationships, to, baseDirectory)...)
    60  				}
    61  				if value, ok := r.To.(file.Location); ok {
    62  					// note: the file.Location is from the SBOM, and all files within the Bitnami SBOM by convention
    63  					// are relative to the /opt/bitnami/PRODUCT directory, so we need to prepend the base directory
    64  					// so that it's relative to the path found within the container image.
    65  					result = append(result, path.Join(baseDirectory, value.RealPath))
    66  				}
    67  			}
    68  		}
    69  	}
    70  
    71  	return result
    72  }
    73  
    74  // mainPkgFiles returns the files owned by the main package in the SPDX file.
    75  func mainPkgFiles(resolver file.Resolver, spdxFilePath string, secondaryPkgsFiles []string) ([]string, error) {
    76  	ownedPathGlob := fmt.Sprintf("%s/**", filepath.Dir(spdxFilePath))
    77  	ownedLocations, err := resolver.FilesByGlob(ownedPathGlob)
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  
    82  	ownedLocationSet := file.NewLocationSet(ownedLocations...)
    83  	ownedFiles := ownedLocationSet.CoordinateSet().Paths()
    84  
    85  	// Remove the SPDX file and the files already assigned to other packages
    86  	// from the list of owned files
    87  	files := slices.DeleteFunc(ownedFiles, func(f string) bool {
    88  		return f == spdxFilePath || slices.Contains(secondaryPkgsFiles, f)
    89  	})
    90  
    91  	return files, nil
    92  }