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 }