feat: add default-image-source-config option (#1215)

#1204 surfaces the need for allowing a user to express a preference over the default-image-pull-source to be used when building an SBOM for vulnerability scanning.

This adds a config option into grype to consume the new syft behavior.

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
This commit is contained in:
Christopher Angelo Phillips 2023-04-04 10:28:33 -04:00 committed by GitHub
parent 0b306fae25
commit 8dec5c3784
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 35 deletions

View file

@ -140,6 +140,12 @@ sbom:path/to/syft.json read Syft JSON from path on disk
registry:yourrepo/yourimage:tag pull image directly from a registry (no container runtime required)
```
If an image source is not provided and cannot be detected from the given reference it is assumed the image should be pulled from the Docker daemon.
If docker is not present, then the Podman daemon is attempted next, followed by reaching out directly to the image registry last.
This default behavior can be overridden with the `default-image-pull-source` configuration option (See [Configuration](https://github.com/anchore/grype#configuration) for more details).
Use SBOMs for even faster vulnerability scanning in Grype:
```
@ -547,6 +553,14 @@ Configuration options (example values are the default):
# same as GRYPE_CHECK_FOR_APP_UPDATE env var
check-for-app-update: true
# allows users to specify which image source should be used to generate the sbom
# valid values are: registry, docker, podman
# same as GRYPE_DEFAULT_IMAGE_PULL_SOURCE env var
default-image-pull-source: ""
# same as --name; set the name of the target being analyzed
name: ""
# upon scanning, if a severity is found at or above the given severity then the return code will be 1
# default is unset which will skip this validation (options: negligible, low, medium, high, critical)
# same as --fail-on ; GRYPE_FAIL_ON_SEVERITY env var

View file

@ -140,6 +140,11 @@ func setRootFlags(flags *pflag.FlagSet) {
"file to write the report output to (default is STDOUT)",
)
flags.StringP(
"name", "", "",
"set the name of the target being analyzed",
)
flags.StringP(
"distro", "", "",
"distro to match against in the format: <distro>:<version>",
@ -243,6 +248,10 @@ func bindRootConfigOptions(flags *pflag.FlagSet) error {
return err
}
if err := viper.BindPFlag("name", flags.Lookup("name")); err != nil {
return err
}
return nil
}
@ -466,10 +475,12 @@ func getMatchers() []matcher.Matcher {
func getProviderConfig() pkg.ProviderConfig {
return pkg.ProviderConfig{
SyftProviderConfig: pkg.SyftProviderConfig{
RegistryOptions: appConfig.Registry.ToOptions(),
Exclusions: appConfig.Exclusions,
CatalogingOptions: appConfig.Search.ToConfig(),
Platform: appConfig.Platform,
RegistryOptions: appConfig.Registry.ToOptions(),
Exclusions: appConfig.Exclusions,
CatalogingOptions: appConfig.Search.ToConfig(),
Platform: appConfig.Platform,
Name: appConfig.Name,
DefaultImagePullSource: appConfig.DefaultImagePullSource,
},
SynthesisConfig: pkg.SynthesisConfig{
GenerateMissingCPEs: appConfig.GenerateMissingCPEs,

View file

@ -11,10 +11,12 @@ type ProviderConfig struct {
}
type SyftProviderConfig struct {
CatalogingOptions cataloger.Config
RegistryOptions *image.RegistryOptions
Platform string
Exclusions []string
CatalogingOptions cataloger.Config
RegistryOptions *image.RegistryOptions
Platform string
Exclusions []string
Name string
DefaultImagePullSource string
}
type SynthesisConfig struct {

View file

@ -11,7 +11,7 @@ func syftProvider(userInput string, config ProviderConfig) ([]Package, Context,
return nil, Context{}, nil, errDoesNotProvide
}
sourceInput, err := source.ParseInput(userInput, config.Platform)
sourceInput, err := source.ParseInputWithName(userInput, config.Platform, config.Name, config.DefaultImagePullSource)
if err != nil {
return nil, Context{}, nil, err
}

View file

@ -29,32 +29,34 @@ type parser interface {
}
type Application struct {
ConfigPath string `yaml:",omitempty" json:"configPath"` // the location where the application config was read from (either from -c or discovered while loading)
Verbosity uint `yaml:"verbosity,omitempty" json:"verbosity" mapstructure:"verbosity"`
Output string `yaml:"output" json:"output" mapstructure:"output"` // -o, the Presenter hint string to use for report formatting
File string `yaml:"file" json:"file" mapstructure:"file"` // --file, the file to write report output to
Distro string `yaml:"distro" json:"distro" mapstructure:"distro"` // --distro, specify a distro to explicitly use
GenerateMissingCPEs bool `yaml:"add-cpes-if-none" json:"add-cpes-if-none" mapstructure:"add-cpes-if-none"` // --add-cpes-if-none, automatically generate CPEs if they are not present in import (e.g. from a 3rd party SPDX document)
OutputTemplateFile string `yaml:"output-template-file" json:"output-template-file" mapstructure:"output-template-file"` // -t, the template file to use for formatting the final report
Quiet bool `yaml:"quiet" json:"quiet" mapstructure:"quiet"` // -q, indicates to not show any status output to stderr (ETUI or logging UI)
CheckForAppUpdate bool `yaml:"check-for-app-update" json:"check-for-app-update" mapstructure:"check-for-app-update"` // whether to check for an application update on start up or not
OnlyFixed bool `yaml:"only-fixed" json:"only-fixed" mapstructure:"only-fixed"` // only fail if detected vulns have a fix
OnlyNotFixed bool `yaml:"only-notfixed" json:"only-notfixed" mapstructure:"only-notfixed"` // only fail if detected vulns don't have a fix
Platform string `yaml:"platform" json:"platform" mapstructure:"platform"` // --platform, override the target platform for a container image
CliOptions CliOnlyOptions `yaml:"-" json:"-"`
Search search `yaml:"search" json:"search" mapstructure:"search"`
Ignore []match.IgnoreRule `yaml:"ignore" json:"ignore" mapstructure:"ignore"`
Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"`
DB database `yaml:"db" json:"db" mapstructure:"db"`
ExternalSources externalSources `yaml:"external-sources" json:"externalSources" mapstructure:"external-sources"`
Match matchConfig `yaml:"match" json:"match" mapstructure:"match"`
Dev development `yaml:"dev" json:"dev" mapstructure:"dev"`
FailOn string `yaml:"fail-on-severity" json:"fail-on-severity" mapstructure:"fail-on-severity"`
FailOnSeverity *vulnerability.Severity `yaml:"-" json:"-"`
Registry registry `yaml:"registry" json:"registry" mapstructure:"registry"`
Log logging `yaml:"log" json:"log" mapstructure:"log"`
ShowSuppressed bool `yaml:"show-suppressed" json:"show-suppressed" mapstructure:"show-suppressed"`
ByCVE bool `yaml:"by-cve" json:"by-cve" mapstructure:"by-cve"` // --by-cve, indicates if the original match vulnerability IDs should be preserved or the CVE should be used instead
ConfigPath string `yaml:",omitempty" json:"configPath"` // the location where the application config was read from (either from -c or discovered while loading)
Verbosity uint `yaml:"verbosity,omitempty" json:"verbosity" mapstructure:"verbosity"`
Output string `yaml:"output" json:"output" mapstructure:"output"` // -o, the Presenter hint string to use for report formatting
File string `yaml:"file" json:"file" mapstructure:"file"` // --file, the file to write report output to
Distro string `yaml:"distro" json:"distro" mapstructure:"distro"` // --distro, specify a distro to explicitly use
GenerateMissingCPEs bool `yaml:"add-cpes-if-none" json:"add-cpes-if-none" mapstructure:"add-cpes-if-none"` // --add-cpes-if-none, automatically generate CPEs if they are not present in import (e.g. from a 3rd party SPDX document)
OutputTemplateFile string `yaml:"output-template-file" json:"output-template-file" mapstructure:"output-template-file"` // -t, the template file to use for formatting the final report
Quiet bool `yaml:"quiet" json:"quiet" mapstructure:"quiet"` // -q, indicates to not show any status output to stderr (ETUI or logging UI)
CheckForAppUpdate bool `yaml:"check-for-app-update" json:"check-for-app-update" mapstructure:"check-for-app-update"` // whether to check for an application update on start up or not
OnlyFixed bool `yaml:"only-fixed" json:"only-fixed" mapstructure:"only-fixed"` // only fail if detected vulns have a fix
OnlyNotFixed bool `yaml:"only-notfixed" json:"only-notfixed" mapstructure:"only-notfixed"` // only fail if detected vulns don't have a fix
Platform string `yaml:"platform" json:"platform" mapstructure:"platform"` // --platform, override the target platform for a container image
CliOptions CliOnlyOptions `yaml:"-" json:"-"`
Search search `yaml:"search" json:"search" mapstructure:"search"`
Ignore []match.IgnoreRule `yaml:"ignore" json:"ignore" mapstructure:"ignore"`
Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"`
DB database `yaml:"db" json:"db" mapstructure:"db"`
ExternalSources externalSources `yaml:"external-sources" json:"externalSources" mapstructure:"external-sources"`
Match matchConfig `yaml:"match" json:"match" mapstructure:"match"`
Dev development `yaml:"dev" json:"dev" mapstructure:"dev"`
FailOn string `yaml:"fail-on-severity" json:"fail-on-severity" mapstructure:"fail-on-severity"`
FailOnSeverity *vulnerability.Severity `yaml:"-" json:"-"`
Registry registry `yaml:"registry" json:"registry" mapstructure:"registry"`
Log logging `yaml:"log" json:"log" mapstructure:"log"`
ShowSuppressed bool `yaml:"show-suppressed" json:"show-suppressed" mapstructure:"show-suppressed"`
ByCVE bool `yaml:"by-cve" json:"by-cve" mapstructure:"by-cve"` // --by-cve, indicates if the original match vulnerability IDs should be preserved or the CVE should be used instead
Name string `yaml:"name" json:"name" mapstructure:"name"`
DefaultImagePullSource string `yaml:"default-image-pull-source" json:"default-image-pull-source" mapstructure:"default-image-pull-source"`
}
func newApplicationConfig(v *viper.Viper, cliOpts CliOnlyOptions) *Application {
@ -90,6 +92,7 @@ func LoadApplicationConfig(v *viper.Viper, cliOpts CliOnlyOptions) (*Application
func (cfg Application) loadDefaultValues(v *viper.Viper) {
// set the default values for primitive fields in this struct
v.SetDefault("check-for-app-update", true)
v.SetDefault("default-image-pull-source", "")
// for each field in the configuration struct, see if the field implements the defaultValueLoader interface and invoke it if it does
value := reflect.ValueOf(cfg)