github.com/lineaje-labs/syft@v0.98.1-0.20231227153149-9e393f60ff1b/cmd/syft/cli/options/catalog.go (about)

     1  package options
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strings"
     7  
     8  	"github.com/iancoleman/strcase"
     9  	"github.com/mitchellh/go-homedir"
    10  	"github.com/scylladb/go-set/strset"
    11  
    12  	"github.com/anchore/clio"
    13  	"github.com/anchore/fangs"
    14  	"github.com/anchore/syft/syft/cataloging"
    15  	"github.com/anchore/syft/syft/pkg/cataloger"
    16  	golangCataloger "github.com/anchore/syft/syft/pkg/cataloger/golang"
    17  	javaCataloger "github.com/anchore/syft/syft/pkg/cataloger/java"
    18  	"github.com/anchore/syft/syft/pkg/cataloger/kernel"
    19  	pythonCataloger "github.com/anchore/syft/syft/pkg/cataloger/python"
    20  	"github.com/anchore/syft/syft/source"
    21  	"github.com/lineaje-labs/syft/internal/log"
    22  )
    23  
    24  type Catalog struct {
    25  	Catalogers                      []string     `yaml:"catalogers" json:"catalogers" mapstructure:"catalogers"`
    26  	Package                         pkg          `yaml:"package" json:"package" mapstructure:"package"`
    27  	Golang                          golang       `yaml:"golang" json:"golang" mapstructure:"golang"`
    28  	Java                            java         `yaml:"java" json:"java" mapstructure:"java"`
    29  	LinuxKernel                     linuxKernel  `yaml:"linux-kernel" json:"linux-kernel" mapstructure:"linux-kernel"`
    30  	Python                          python       `yaml:"python" json:"python" mapstructure:"python"`
    31  	FileMetadata                    fileMetadata `yaml:"file-metadata" json:"file-metadata" mapstructure:"file-metadata"`
    32  	FileContents                    fileContents `yaml:"file-contents" json:"file-contents" mapstructure:"file-contents"`
    33  	Registry                        registry     `yaml:"registry" json:"registry" mapstructure:"registry"`
    34  	Exclusions                      []string     `yaml:"exclude" json:"exclude" mapstructure:"exclude"`
    35  	Platform                        string       `yaml:"platform" json:"platform" mapstructure:"platform"`
    36  	Name                            string       `yaml:"name" json:"name" mapstructure:"name"`
    37  	Source                          sourceCfg    `yaml:"source" json:"source" mapstructure:"source"`
    38  	Parallelism                     int          `yaml:"parallelism" json:"parallelism" mapstructure:"parallelism"`                                                                         // the number of catalog workers to run in parallel
    39  	DefaultImagePullSource          string       `yaml:"default-image-pull-source" json:"default-image-pull-source" mapstructure:"default-image-pull-source"`                               // specify default image pull source
    40  	BasePath                        string       `yaml:"base-path" json:"base-path" mapstructure:"base-path"`                                                                               // specify base path for all file paths
    41  	ExcludeBinaryOverlapByOwnership bool         `yaml:"exclude-binary-overlap-by-ownership" json:"exclude-binary-overlap-by-ownership" mapstructure:"exclude-binary-overlap-by-ownership"` // exclude synthetic binary packages owned by os package files
    42  	CleanupDisabled                 bool         `yaml:"cleanup-disabled" json:"cleanup-disabled" mapstructure:"cleanup-disabled"`
    43  }
    44  
    45  var _ interface {
    46  	clio.FlagAdder
    47  	clio.PostLoader
    48  } = (*Catalog)(nil)
    49  
    50  func DefaultCatalog() Catalog {
    51  	return Catalog{
    52  		Package:                         defaultPkg(),
    53  		LinuxKernel:                     defaultLinuxKernel(),
    54  		FileMetadata:                    defaultFileMetadata(),
    55  		FileContents:                    defaultFileContents(),
    56  		Source:                          defaultSourceCfg(),
    57  		Parallelism:                     1,
    58  		ExcludeBinaryOverlapByOwnership: true,
    59  		CleanupDisabled:                 false,
    60  	}
    61  }
    62  
    63  func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
    64  	var validScopeValues []string
    65  	for _, scope := range source.AllScopes {
    66  		validScopeValues = append(validScopeValues, strcase.ToDelimited(string(scope), '-'))
    67  	}
    68  	flags.StringVarP(&cfg.Package.Cataloger.Scope, "scope", "s",
    69  		fmt.Sprintf("selection of layers to catalog, options=%v", validScopeValues))
    70  
    71  	flags.StringVarP(&cfg.Platform, "platform", "",
    72  		"an optional platform specifier for container image sources (e.g. 'linux/arm64', 'linux/arm64/v8', 'arm64', 'linux')")
    73  
    74  	flags.StringArrayVarP(&cfg.Exclusions, "exclude", "",
    75  		"exclude paths from being scanned using a glob expression")
    76  
    77  	flags.StringArrayVarP(&cfg.Catalogers, "catalogers", "",
    78  		"enable one or more package catalogers")
    79  
    80  	flags.StringVarP(&cfg.Source.Name, "name", "",
    81  		"set the name of the target being analyzed")
    82  
    83  	if pfp, ok := flags.(fangs.PFlagSetProvider); ok {
    84  		flagSet := pfp.PFlagSet()
    85  		flagSet.Lookup("name").Deprecated = "use: source-name"
    86  	}
    87  
    88  	flags.StringVarP(&cfg.Source.Name, "source-name", "",
    89  		"set the name of the target being analyzed")
    90  
    91  	flags.StringVarP(&cfg.Source.Version, "source-version", "",
    92  		"set the version of the target being analyzed")
    93  
    94  	flags.StringVarP(&cfg.BasePath, "base-path", "",
    95  		"base directory for scanning, no links will be followed above this directory, and all paths will be reported relative to this directory")
    96  
    97  	flags.BoolVarP(&cfg.CleanupDisabled, "cleanup-disabled", "",
    98  		"do not clean any temporary directories created during sbom generation (default false)")
    99  }
   100  
   101  func (cfg *Catalog) PostLoad() error {
   102  	// parse options on this struct
   103  	var catalogers []string
   104  	for _, c := range cfg.Catalogers {
   105  		for _, f := range strings.Split(c, ",") {
   106  			catalogers = append(catalogers, strings.TrimSpace(f))
   107  		}
   108  	}
   109  	sort.Strings(catalogers)
   110  	cfg.Catalogers = catalogers
   111  
   112  	if err := checkDefaultSourceValues(cfg.DefaultImagePullSource); err != nil {
   113  		return err
   114  	}
   115  
   116  	if cfg.Name != "" {
   117  		log.Warnf("name parameter is deprecated. please use: source-name. name will be removed in a future version")
   118  		if cfg.Source.Name == "" {
   119  			cfg.Source.Name = cfg.Name
   120  		}
   121  	}
   122  
   123  	return nil
   124  }
   125  
   126  func (cfg Catalog) ToCatalogerConfig() cataloger.Config {
   127  	return cataloger.Config{
   128  		Search: cataloger.SearchConfig{
   129  			IncludeIndexedArchives:   cfg.Package.SearchIndexedArchives,
   130  			IncludeUnindexedArchives: cfg.Package.SearchUnindexedArchives,
   131  			Scope:                    cfg.Package.Cataloger.GetScope(),
   132  		},
   133  		Catalogers:  cfg.Catalogers,
   134  		Parallelism: cfg.Parallelism,
   135  		Golang: golangCataloger.DefaultCatalogerConfig().
   136  			WithSearchLocalModCacheLicenses(cfg.Golang.SearchLocalModCacheLicenses).
   137  			WithLocalModCacheDir(cfg.Golang.LocalModCacheDir).
   138  			WithSearchRemoteLicenses(cfg.Golang.SearchRemoteLicenses).
   139  			WithProxy(cfg.Golang.Proxy).
   140  			WithNoProxy(cfg.Golang.NoProxy),
   141  		LinuxKernel: kernel.LinuxKernelCatalogerConfig{
   142  			CatalogModules: cfg.LinuxKernel.CatalogModules,
   143  		},
   144  		Java: javaCataloger.DefaultArchiveCatalogerConfig().
   145  			WithUseNetwork(cfg.Java.UseNetwork).
   146  			WithMavenBaseURL(cfg.Java.MavenURL).
   147  			WithArchiveTraversal(
   148  				cataloging.ArchiveSearchConfig{
   149  					IncludeIndexedArchives:   cfg.Package.SearchIndexedArchives,
   150  					IncludeUnindexedArchives: cfg.Package.SearchUnindexedArchives,
   151  				},
   152  				cfg.Java.MaxParentRecursiveDepth),
   153  		Python: pythonCataloger.CatalogerConfig{
   154  			GuessUnpinnedRequirements: cfg.Python.GuessUnpinnedRequirements,
   155  		},
   156  		ExcludeBinaryOverlapByOwnership: cfg.ExcludeBinaryOverlapByOwnership,
   157  		CleanupDisabled:                 cfg.CleanupDisabled,
   158  	}
   159  }
   160  
   161  var validDefaultSourceValues = []string{"registry", "docker", "podman", ""}
   162  
   163  func checkDefaultSourceValues(source string) error {
   164  	validValues := strset.New(validDefaultSourceValues...)
   165  	if !validValues.Has(source) {
   166  		validValuesString := strings.Join(validDefaultSourceValues, ", ")
   167  		return fmt.Errorf("%s is not a valid default source; please use one of the following: %s''", source, validValuesString)
   168  	}
   169  
   170  	return nil
   171  }
   172  
   173  func expandFilePath(file string) (string, error) {
   174  	if file != "" {
   175  		expandedPath, err := homedir.Expand(file)
   176  		if err != nil {
   177  			return "", fmt.Errorf("unable to expand file path=%q: %w", file, err)
   178  		}
   179  		file = expandedPath
   180  	}
   181  	return file, nil
   182  }