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