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

     1  package nix
     2  
     3  import (
     4  	"path"
     5  	"sort"
     6  
     7  	"github.com/anchore/packageurl-go"
     8  	"github.com/anchore/syft/syft/file"
     9  	"github.com/anchore/syft/syft/pkg"
    10  )
    11  
    12  type nixStorePackage struct {
    13  	Location *file.Location
    14  	Files    []string
    15  	*derivationFile
    16  	nixStorePath
    17  }
    18  
    19  func newNixStorePackage(pp nixStorePackage, catalogerName string) pkg.Package {
    20  	locations := file.NewLocationSet(pp.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation))
    21  
    22  	var derivationPath string
    23  	if pp.derivationFile != nil {
    24  		derivationPath = pp.derivationFile.Location.RealPath
    25  		locations.Add(pp.derivationFile.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation))
    26  	}
    27  
    28  	p := pkg.Package{
    29  		Name:      pp.Name,
    30  		Version:   pp.Version,
    31  		FoundBy:   catalogerName,
    32  		Locations: locations,
    33  		Type:      pkg.NixPkg,
    34  		PURL:      packageURL(pp.nixStorePath, derivationPath),
    35  		Metadata: pkg.NixStoreEntry{
    36  			Path:       pp.StorePath,
    37  			Derivation: newDerivation(pp.derivationFile),
    38  			OutputHash: pp.OutputHash,
    39  			Output:     pp.Output,
    40  			Files:      pp.Files,
    41  		},
    42  	}
    43  
    44  	p.SetID()
    45  
    46  	return p
    47  }
    48  
    49  func newDBPackage(entry *dbPackageEntry, catalogerName string) pkg.Package {
    50  	locations := file.NewLocationSet(
    51  		entry.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
    52  		file.NewLocation(entry.StorePath).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation),
    53  	)
    54  	if entry.derivationFile != nil {
    55  		locations.Add(entry.derivationFile.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation))
    56  	}
    57  
    58  	p := pkg.Package{
    59  		Name:      entry.Name,
    60  		Version:   entry.Version,
    61  		FoundBy:   catalogerName,
    62  		Locations: locations,
    63  		Type:      pkg.NixPkg,
    64  		PURL:      packageURL(entry.nixStorePath, entry.DeriverPath),
    65  		Metadata: pkg.NixStoreEntry{
    66  			Path:       entry.StorePath,
    67  			Derivation: newDerivation(entry.derivationFile),
    68  			OutputHash: entry.OutputHash,
    69  			Output:     entry.Output,
    70  			Files:      entry.Files,
    71  		},
    72  	}
    73  
    74  	p.SetID()
    75  
    76  	return p
    77  }
    78  
    79  func newDerivation(df *derivationFile) pkg.NixDerivation {
    80  	if df == nil {
    81  		return pkg.NixDerivation{}
    82  	}
    83  
    84  	var inputDerivations []pkg.NixDerivationReference
    85  	for drvPath, names := range df.InputDerivations {
    86  		sort.Strings(names)
    87  		inputDerivations = append(inputDerivations, pkg.NixDerivationReference{
    88  			Path:    drvPath,
    89  			Outputs: names,
    90  		})
    91  	}
    92  	sort.Slice(inputDerivations, func(i, j int) bool {
    93  		return inputDerivations[i].Path < inputDerivations[j].Path
    94  	})
    95  
    96  	sources := df.InputSources
    97  	sort.Strings(sources)
    98  
    99  	return pkg.NixDerivation{
   100  		Path:             df.Location.RealPath,
   101  		System:           df.Platform,
   102  		InputDerivations: inputDerivations,
   103  		InputSources:     sources,
   104  	}
   105  }
   106  
   107  func packageURL(storePath nixStorePath, drvPath string) string {
   108  	var qualifiers packageurl.Qualifiers
   109  	if storePath.Output != "" {
   110  		// since there is no nix pURL type yet, this is a guess, however, it is reasonable to assume that
   111  		// if only a single output is installed the pURL should be able to express this.
   112  		qualifiers = append(qualifiers,
   113  			packageurl.Qualifier{
   114  				Key:   "output",
   115  				Value: storePath.Output,
   116  			},
   117  		)
   118  	}
   119  	if storePath.OutputHash != "" {
   120  		qualifiers = append(qualifiers,
   121  			packageurl.Qualifier{
   122  				Key:   "outputhash",
   123  				Value: storePath.OutputHash,
   124  			},
   125  		)
   126  	}
   127  
   128  	if drvPath != "" {
   129  		qualifiers = append(qualifiers,
   130  			packageurl.Qualifier{
   131  				Key:   "drvpath",
   132  				Value: path.Base(drvPath),
   133  			},
   134  		)
   135  	}
   136  	pURL := packageurl.NewPackageURL(
   137  		// TODO: nix pURL type has not been accepted yet (only proposed at this time)
   138  		"nix",
   139  		"",
   140  		storePath.Name,
   141  		storePath.Version,
   142  		qualifiers,
   143  		"")
   144  	return pURL.ToString()
   145  }