feat(vuln): add --pkg-relationships (#7237)

Signed-off-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
Teppei Fukuda
2024-07-29 10:18:59 +04:00
committed by GitHub
parent f35f4a5e83
commit 5c37361600
27 changed files with 580 additions and 278 deletions

View File

@@ -63,7 +63,8 @@ trivy filesystem [flags] PATH
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
--parallel int number of goroutines enabled for parallel scanning, set 0 to auto-detect parallelism (default 5)
--password strings password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons.
--pkg-types strings comma-separated list of package types (os,library) (default [os,library])
--pkg-relationships strings list of package relationships (unknown,root,direct,indirect) (default [unknown,root,direct,indirect])
--pkg-types strings list of package types (os,library) (default [os,library])
--redis-ca string redis ca file location, if using redis as cache backend
--redis-cert string redis certificate file location, if using redis as cache backend
--redis-key string redis key file location, if using redis as cache backend

View File

@@ -81,7 +81,8 @@ trivy image [flags] IMAGE_NAME
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
--parallel int number of goroutines enabled for parallel scanning, set 0 to auto-detect parallelism (default 5)
--password strings password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons.
--pkg-types strings comma-separated list of package types (os,library) (default [os,library])
--pkg-relationships strings list of package relationships (unknown,root,direct,indirect) (default [unknown,root,direct,indirect])
--pkg-types strings list of package types (os,library) (default [os,library])
--platform string set platform in the form os/arch if image is multi-platform capable
--podman-host string unix podman socket path to use for podman scanning
--redis-ca string redis ca file location, if using redis as cache backend

View File

@@ -78,7 +78,8 @@ trivy kubernetes [flags] [CONTEXT]
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
--parallel int number of goroutines enabled for parallel scanning, set 0 to auto-detect parallelism (default 5)
--password strings password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons.
--pkg-types strings comma-separated list of package types (os,library) (default [os,library])
--pkg-relationships strings list of package relationships (unknown,root,direct,indirect) (default [unknown,root,direct,indirect])
--pkg-types strings list of package types (os,library) (default [os,library])
--qps float specify the maximum QPS to the master from this client (default 5)
--redis-ca string redis ca file location, if using redis as cache backend
--redis-cert string redis certificate file location, if using redis as cache backend

View File

@@ -63,7 +63,8 @@ trivy repository [flags] (REPO_PATH | REPO_URL)
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
--parallel int number of goroutines enabled for parallel scanning, set 0 to auto-detect parallelism (default 5)
--password strings password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons.
--pkg-types strings comma-separated list of package types (os,library) (default [os,library])
--pkg-relationships strings list of package relationships (unknown,root,direct,indirect) (default [unknown,root,direct,indirect])
--pkg-types strings list of package types (os,library) (default [os,library])
--redis-ca string redis ca file location, if using redis as cache backend
--redis-cert string redis certificate file location, if using redis as cache backend
--redis-key string redis key file location, if using redis as cache backend

View File

@@ -65,7 +65,8 @@ trivy rootfs [flags] ROOTDIR
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
--parallel int number of goroutines enabled for parallel scanning, set 0 to auto-detect parallelism (default 5)
--password strings password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons.
--pkg-types strings comma-separated list of package types (os,library) (default [os,library])
--pkg-relationships strings list of package relationships (unknown,root,direct,indirect) (default [unknown,root,direct,indirect])
--pkg-types strings list of package types (os,library) (default [os,library])
--redis-ca string redis ca file location, if using redis as cache backend
--redis-cert string redis certificate file location, if using redis as cache backend
--redis-key string redis key file location, if using redis as cache backend

View File

@@ -43,7 +43,8 @@ trivy sbom [flags] SBOM_PATH
--offline-scan do not issue API requests to identify dependencies
-o, --output string output file name
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
--pkg-types strings comma-separated list of package types (os,library) (default [os,library])
--pkg-relationships strings list of package relationships (unknown,root,direct,indirect) (default [unknown,root,direct,indirect])
--pkg-types strings list of package types (os,library) (default [os,library])
--redis-ca string redis ca file location, if using redis as cache backend
--redis-cert string redis certificate file location, if using redis as cache backend
--redis-key string redis key file location, if using redis as cache backend

View File

@@ -56,7 +56,8 @@ trivy vm [flags] VM_IMAGE
-o, --output string output file name
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
--parallel int number of goroutines enabled for parallel scanning, set 0 to auto-detect parallelism (default 5)
--pkg-types strings comma-separated list of package types (os,library) (default [os,library])
--pkg-relationships strings list of package relationships (unknown,root,direct,indirect) (default [unknown,root,direct,indirect])
--pkg-types strings list of package types (os,library) (default [os,library])
--redis-ca string redis ca file location, if using redis as cache backend
--redis-cert string redis certificate file location, if using redis as cache backend
--redis-key string redis key file location, if using redis as cache backend

View File

@@ -202,7 +202,8 @@ Currently, specifying a username and password is not supported.
This section describes vulnerability-specific configuration.
Other common options are documented [here](../configuration/index.md).
### Enabling a subset of package types
### Enabling a Subset of Package Types
It's possible to only enable certain package types if you prefer.
You can do so by passing the `--pkg-types` option.
This flag takes a comma-separated list of package types.
@@ -268,6 +269,45 @@ Total: 7 (UNKNOWN: 0, LOW: 1, MEDIUM: 1, HIGH: 3, CRITICAL: 2)
</details>
!!! info
This flag filters the packages themselves, so it also affects the `--list-all-pkgs` option and SBOM generation.
### Filtering by Package Relationships
Trivy supports filtering vulnerabilities based on the relationship of packages within a project.
This is achieved through the `--pkg-relationships` flag.
This feature allows you to focus on vulnerabilities in specific types of dependencies, such as only those in direct dependencies.
In Trivy, there are four types of package relationships:
1. `root`: The root package being scanned
2. `direct`: Direct dependencies of the root package
3. `indirect`: Transitive dependencies
4. `unknown`: Packages whose relationship cannot be determined
The available relationships may vary depending on the ecosystem.
To see which relationships are supported for a particular project, you can use the JSON output format and check the `Relationship` field:
```
$ trivy repo -f json --list-all-pkgs /path/to/project
```
To scan only the root package and its direct dependencies, you can use the flag as follows:
```
$ trivy repo --pkg-relationships root,direct /path/to/project
```
By default, all relationships are included in the scan.
!!! info
This flag filters the packages themselves, so it also affects the `--list-all-pkgs` option and SBOM generation.
!!! warning
As it may not provide a complete package list, `--pkg-relationships` cannot be used with `--dependency-tree`, `--vex` or SBOM generation.
[^1]: https://github.com/GoogleContainerTools/distroless
[nvd-CVE-2023-0464]: https://nvd.nist.gov/vuln/detail/CVE-2023-0464

View File

@@ -243,9 +243,6 @@ func NewRootCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
}
func NewImageCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
scanFlagGroup := flag.NewScanFlagGroup()
scanFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
reportFlagGroup := flag.NewReportFlagGroup()
report := flag.ReportFormatFlag.Clone()
report.Default = "summary" // override the default value as the summary is preferred for the compliance report
@@ -256,27 +253,28 @@ func NewImageCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
compliance.Values = []string{types.ComplianceDockerCIS160}
reportFlagGroup.Compliance = compliance // override usage as the accepted values differ for each subcommand.
misconfFlagGroup := flag.NewMisconfFlagGroup()
misconfFlagGroup.CloudformationParamVars = nil // disable '--cf-params'
misconfFlagGroup.TerraformTFVars = nil // disable '--tf-vars'
imageFlags := &flag.Flags{
GlobalFlagGroup: globalFlags,
CacheFlagGroup: flag.NewCacheFlagGroup(),
DBFlagGroup: flag.NewDBFlagGroup(),
ImageFlagGroup: flag.NewImageFlagGroup(), // container image specific
LicenseFlagGroup: flag.NewLicenseFlagGroup(),
MisconfFlagGroup: misconfFlagGroup,
MisconfFlagGroup: flag.NewMisconfFlagGroup(),
ModuleFlagGroup: flag.NewModuleFlagGroup(),
PackageFlagGroup: flag.NewPackageFlagGroup(),
RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
RegoFlagGroup: flag.NewRegoFlagGroup(),
ReportFlagGroup: reportFlagGroup,
ScanFlagGroup: scanFlagGroup,
ScanFlagGroup: flag.NewScanFlagGroup(),
SecretFlagGroup: flag.NewSecretFlagGroup(),
VulnerabilityFlagGroup: flag.NewVulnerabilityFlagGroup(),
}
imageFlags.PackageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
imageFlags.MisconfFlagGroup.CloudformationParamVars = nil // disable '--cf-params'
imageFlags.MisconfFlagGroup.TerraformTFVars = nil // disable '--tf-vars'
cmd := &cobra.Command{
Use: "image [flags] IMAGE_NAME",
Aliases: []string{"i"},
@@ -342,6 +340,7 @@ func NewFilesystemCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
LicenseFlagGroup: flag.NewLicenseFlagGroup(),
MisconfFlagGroup: flag.NewMisconfFlagGroup(),
ModuleFlagGroup: flag.NewModuleFlagGroup(),
PackageFlagGroup: flag.NewPackageFlagGroup(),
RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
RegoFlagGroup: flag.NewRegoFlagGroup(),
@@ -400,6 +399,7 @@ func NewRootfsCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
LicenseFlagGroup: flag.NewLicenseFlagGroup(),
MisconfFlagGroup: flag.NewMisconfFlagGroup(),
ModuleFlagGroup: flag.NewModuleFlagGroup(),
PackageFlagGroup: flag.NewPackageFlagGroup(),
RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
RegoFlagGroup: flag.NewRegoFlagGroup(),
@@ -411,7 +411,7 @@ func NewRootfsCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
rootfsFlags.ReportFlagGroup.ReportFormat = nil // TODO: support --report summary
rootfsFlags.ReportFlagGroup.Compliance = nil // disable '--compliance'
rootfsFlags.ReportFlagGroup.ReportFormat = nil // disable '--report'
rootfsFlags.ScanFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
rootfsFlags.PackageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
rootfsFlags.CacheFlagGroup.CacheBackend.Default = string(cache.TypeMemory) // Use memory cache by default
cmd := &cobra.Command{
@@ -460,6 +460,7 @@ func NewRepositoryCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
LicenseFlagGroup: flag.NewLicenseFlagGroup(),
MisconfFlagGroup: flag.NewMisconfFlagGroup(),
ModuleFlagGroup: flag.NewModuleFlagGroup(),
PackageFlagGroup: flag.NewPackageFlagGroup(),
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
RegoFlagGroup: flag.NewRegoFlagGroup(),
RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode
@@ -516,7 +517,6 @@ func NewConvertCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
ScanFlagGroup: &flag.ScanFlagGroup{},
ReportFlagGroup: flag.NewReportFlagGroup(),
}
convertFlags.ReportFlagGroup.PkgTypes = nil // disable '--pkg-types'
cmd := &cobra.Command{
Use: "convert [flags] RESULT_JSON",
@@ -685,7 +685,6 @@ func NewConfigCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
configFlags.ReportFlagGroup.ListAllPkgs = nil // disable '--list-all-pkgs'
configFlags.ReportFlagGroup.ExitOnEOL = nil // disable '--exit-on-eol'
configFlags.ReportFlagGroup.ShowSuppressed = nil // disable '--show-suppressed'
configFlags.ReportFlagGroup.PkgTypes = nil // disable '--pkg-types'
configFlags.ReportFlagGroup.ReportFormat.Usage = "specify a compliance report format for the output" // @TODO: support --report summary for non compliance reports
configFlags.CacheFlagGroup.CacheBackend.Default = string(cache.TypeMemory)
@@ -960,7 +959,6 @@ func NewKubernetesCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
})
scanners.Default = scanners.Values
scanFlags.Scanners = scanners
scanFlags.IncludeDevDeps = nil // disable '--include-dev-deps'
// required only SourceFlag
imageFlags := &flag.ImageFlagGroup{ImageSources: flag.SourceFlag.Clone()}
@@ -997,6 +995,7 @@ func NewKubernetesCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
ImageFlagGroup: imageFlags,
K8sFlagGroup: flag.NewK8sFlagGroup(), // kubernetes-specific flags
MisconfFlagGroup: misconfFlagGroup,
PackageFlagGroup: flag.NewPackageFlagGroup(),
RegoFlagGroup: flag.NewRegoFlagGroup(),
ReportFlagGroup: reportFlagGroup,
ScanFlagGroup: scanFlags,
@@ -1004,6 +1003,8 @@ func NewKubernetesCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
RegistryFlagGroup: flag.NewRegistryFlagGroup(),
VulnerabilityFlagGroup: flag.NewVulnerabilityFlagGroup(),
}
k8sFlags.PackageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
cmd := &cobra.Command{
Use: "kubernetes [flags] [CONTEXT]",
Aliases: []string{"k8s"},
@@ -1055,6 +1056,7 @@ func NewVMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
DBFlagGroup: flag.NewDBFlagGroup(),
MisconfFlagGroup: flag.NewMisconfFlagGroup(),
ModuleFlagGroup: flag.NewModuleFlagGroup(),
PackageFlagGroup: flag.NewPackageFlagGroup(),
RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode
ReportFlagGroup: flag.NewReportFlagGroup(),
ScanFlagGroup: flag.NewScanFlagGroup(),
@@ -1069,7 +1071,7 @@ func NewVMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
},
}
vmFlags.ReportFlagGroup.ReportFormat = nil // disable '--report'
vmFlags.ScanFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
vmFlags.PackageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
vmFlags.MisconfFlagGroup.CloudformationParamVars = nil // disable '--cf-params'
vmFlags.MisconfFlagGroup.TerraformTFVars = nil // disable '--tf-vars'
@@ -1129,7 +1131,6 @@ func NewSBOMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
})
scanFlagGroup := flag.NewScanFlagGroup()
scanFlagGroup.Scanners = scanners // allow only 'vuln' and 'license' options for '--scanners'
scanFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
scanFlagGroup.Parallel = nil // disable '--parallel'
licenseFlagGroup := flag.NewLicenseFlagGroup()
@@ -1141,6 +1142,7 @@ func NewSBOMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
GlobalFlagGroup: globalFlags,
CacheFlagGroup: flag.NewCacheFlagGroup(),
DBFlagGroup: flag.NewDBFlagGroup(),
PackageFlagGroup: flag.NewPackageFlagGroup(),
RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode
ReportFlagGroup: reportFlagGroup,
ScanFlagGroup: scanFlagGroup,
@@ -1150,6 +1152,7 @@ func NewSBOMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
}
sbomFlags.CacheFlagGroup.CacheBackend.Default = string(cache.TypeMemory) // Use memory cache by default
sbomFlags.PackageFlagGroup.IncludeDevDeps = nil // disable '--include-dev-deps'
cmd := &cobra.Command{
Use: "sbom [flags] SBOM_PATH",

View File

@@ -479,6 +479,7 @@ func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.Scan
scanOptions := types.ScanOptions{
PkgTypes: opts.PkgTypes,
PkgRelationships: opts.PkgRelationships,
Scanners: opts.Scanners,
ImageConfigScanners: opts.ImageConfigScanners, // this is valid only for 'image' subcommand
ScanRemovedPackages: opts.ScanRemovedPkgs, // this is valid only for 'image' subcommand
@@ -488,18 +489,24 @@ func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.Scan
}
if len(opts.ImageConfigScanners) != 0 {
log.Info("Container image config scanners", log.Any("scanners", opts.ImageConfigScanners))
log.WithPrefix(log.PrefixContainerImage).Info("Container image config scanners", log.Any("scanners", opts.ImageConfigScanners))
}
if opts.Scanners.Enabled(types.SBOMScanner) {
logger := log.WithPrefix(log.PrefixPackage)
logger.Debug("Package types", log.Any("types", scanOptions.PkgTypes))
logger.Debug("Package relationships", log.Any("relationships", scanOptions.PkgRelationships))
}
if opts.Scanners.Enabled(types.VulnerabilityScanner) {
log.Info("Vulnerability scanning is enabled")
log.Debug("Package types", log.Any("types", scanOptions.PkgTypes))
log.WithPrefix(log.PrefixVulnerability).Info("Vulnerability scanning is enabled")
}
// ScannerOption is filled only when config scanning is enabled.
var configScannerOptions misconf.ScannerOption
if opts.Scanners.Enabled(types.MisconfigScanner) || opts.ImageConfigScanners.Enabled(types.MisconfigScanner) {
log.Info("Misconfiguration scanning is enabled")
logger := log.WithPrefix(log.PrefixMisconfiguration)
logger.Info("Misconfiguration scanning is enabled")
var downloadedPolicyPaths []string
var disableEmbedded bool
@@ -507,10 +514,10 @@ func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.Scan
downloadedPolicyPaths, err := operation.InitBuiltinPolicies(context.Background(), opts.CacheDir, opts.Quiet, opts.SkipCheckUpdate, opts.MisconfOptions.ChecksBundleRepository, opts.RegistryOpts())
if err != nil {
if !opts.SkipCheckUpdate {
log.Error("Falling back to embedded checks", log.Err(err))
logger.Error("Falling back to embedded checks", log.Err(err))
}
} else {
log.Debug("Policies successfully loaded from disk")
logger.Debug("Policies successfully loaded from disk")
disableEmbedded = true
}
configScannerOptions = misconf.ScannerOption{
@@ -537,19 +544,21 @@ func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.Scan
// Do not load config file for secret scanning
if opts.Scanners.Enabled(types.SecretScanner) {
log.Info("Secret scanning is enabled")
log.Info("If your scanning is slow, please try '--scanners vuln' to disable secret scanning")
logger := log.WithPrefix(log.PrefixSecret)
logger.Info("Secret scanning is enabled")
logger.Info("If your scanning is slow, please try '--scanners vuln' to disable secret scanning")
// e.g. https://aquasecurity.github.io/trivy/latest/docs/scanner/secret/#recommendation
log.Infof("Please see also %s for faster secret detection", doc.URL("/docs/scanner/secret/", "recommendation"))
logger.Info(fmt.Sprintf("Please see also %s for faster secret detection", doc.URL("/docs/scanner/secret/", "recommendation")))
} else {
opts.SecretConfigPath = ""
}
if opts.Scanners.Enabled(types.LicenseScanner) {
logger := log.WithPrefix(log.PrefixLicense)
if opts.LicenseFull {
log.Info("Full license scanning is enabled")
logger.Info("Full license scanning is enabled")
} else {
log.Info("License scanning is enabled")
logger.Info("License scanning is enabled")
}
}

View File

@@ -20,12 +20,30 @@ const (
RelationshipIndirect
)
var relationshipNames = [...]string{
var (
Relationships = []Relationship{
RelationshipUnknown,
RelationshipRoot,
RelationshipDirect,
RelationshipIndirect,
}
relationshipNames = [...]string{
"unknown",
"root",
"direct",
"indirect",
}
)
func NewRelationship(s string) (Relationship, error) {
for i, name := range relationshipNames {
if s == name {
return Relationship(i), nil
}
}
return RelationshipUnknown, xerrors.Errorf("invalid relationship (%s)", s)
}
func (r Relationship) String() string {
if r <= RelationshipUnknown || int(r) >= len(relationshipNames) {

View File

@@ -320,6 +320,7 @@ type Flags struct {
LicenseFlagGroup *LicenseFlagGroup
MisconfFlagGroup *MisconfFlagGroup
ModuleFlagGroup *ModuleFlagGroup
PackageFlagGroup *PackageFlagGroup
RemoteFlagGroup *RemoteFlagGroup
RegistryFlagGroup *RegistryFlagGroup
RegoFlagGroup *RegoFlagGroup
@@ -343,6 +344,7 @@ type Options struct {
LicenseOptions
MisconfOptions
ModuleOptions
PackageOptions
RegistryOptions
RegoOptions
RemoteOptions
@@ -370,6 +372,12 @@ func (o *Options) Align(f *Flags) error {
o.enableSBOM()
}
if f.PackageFlagGroup != nil && f.PackageFlagGroup.PkgRelationships != nil &&
slices.Compare(o.PkgRelationships, ftypes.Relationships) != 0 &&
(o.DependencyTree || slices.Contains(types.SupportedSBOMFormats, o.Format) || len(o.VEXSources) != 0) {
return xerrors.Errorf("'--pkg-relationships' cannot be used with '--dependency-tree', '--vex' or SBOM formats")
}
if o.Compliance.Spec.ID != "" {
if viper.IsSet(ScannersFlag.ConfigName) {
log.Info(`The option to change scanners is disabled for scanning with the "--compliance" flag. Default scanners used.`)
@@ -568,6 +576,9 @@ func (f *Flags) groups() []FlagGroup {
if f.K8sFlagGroup != nil {
groups = append(groups, f.K8sFlagGroup)
}
if f.PackageFlagGroup != nil {
groups = append(groups, f.PackageFlagGroup)
}
if f.RemoteFlagGroup != nil {
groups = append(groups, f.RemoteFlagGroup)
}
@@ -707,6 +718,13 @@ func (f *Flags) ToOptions(args []string) (Options, error) {
}
}
if f.PackageFlagGroup != nil {
opts.PackageOptions, err = f.PackageFlagGroup.ToOptions()
if err != nil {
return Options{}, xerrors.Errorf("package flag error: %w", err)
}
}
if f.RegoFlagGroup != nil {
opts.RegoOptions, err = f.RegoFlagGroup.ToOptions()
if err != nil {

91
pkg/flag/package_flags.go Normal file
View File

@@ -0,0 +1,91 @@
package flag
import (
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/types"
xstrings "github.com/aquasecurity/trivy/pkg/x/strings"
)
var (
IncludeDevDepsFlag = Flag[bool]{
Name: "include-dev-deps",
ConfigName: "pkg.include-dev-deps",
Usage: "include development dependencies in the report (supported: npm, yarn)",
}
PkgTypesFlag = Flag[[]string]{
Name: "pkg-types",
ConfigName: "pkg.types",
Default: types.PkgTypes,
Values: types.PkgTypes,
Usage: "list of package types",
Aliases: []Alias{
{
Name: "vuln-type",
ConfigName: "vulnerability.type",
Deprecated: true, // --vuln-type was renamed to --pkg-types
},
},
}
PkgRelationshipsFlag = Flag[[]string]{
Name: "pkg-relationships",
ConfigName: "pkg.relationships",
Default: xstrings.ToStringSlice(ftypes.Relationships),
Values: xstrings.ToStringSlice(ftypes.Relationships),
Usage: "list of package relationships",
}
)
// PackageFlagGroup composes common package flag structs.
// These flags affect both SBOM and vulnerability scanning.
type PackageFlagGroup struct {
IncludeDevDeps *Flag[bool]
PkgTypes *Flag[[]string]
PkgRelationships *Flag[[]string]
}
type PackageOptions struct {
IncludeDevDeps bool
PkgTypes []string
PkgRelationships []ftypes.Relationship
}
func NewPackageFlagGroup() *PackageFlagGroup {
return &PackageFlagGroup{
IncludeDevDeps: IncludeDevDepsFlag.Clone(),
PkgTypes: PkgTypesFlag.Clone(),
PkgRelationships: PkgRelationshipsFlag.Clone(),
}
}
func (f *PackageFlagGroup) Name() string {
return "Package"
}
func (f *PackageFlagGroup) Flags() []Flagger {
return []Flagger{
f.IncludeDevDeps,
f.PkgTypes,
f.PkgRelationships,
}
}
func (f *PackageFlagGroup) ToOptions() (PackageOptions, error) {
if err := parseFlags(f); err != nil {
return PackageOptions{}, err
}
var relationships []ftypes.Relationship
for _, r := range f.PkgRelationships.Value() {
relationship, err := ftypes.NewRelationship(r)
if err != nil {
return PackageOptions{}, err
}
relationships = append(relationships, relationship)
}
return PackageOptions{
IncludeDevDeps: f.IncludeDevDeps.Value(),
PkgTypes: f.PkgTypes.Value(),
PkgRelationships: relationships,
}, nil
}

View File

@@ -0,0 +1,84 @@
package flag_test
import (
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/flag"
"github.com/aquasecurity/trivy/pkg/types"
)
func TestPackageFlagGroup_ToOptions(t *testing.T) {
type fields struct {
pkgTypes string
pkgRelationships string
}
tests := []struct {
name string
fields fields
want flag.PackageOptions
wantLogs []string
}{
{
name: "happy default (without flags)",
fields: fields{},
want: flag.PackageOptions{},
},
{
name: "happy path for OS packages",
fields: fields{
pkgTypes: "os",
},
want: flag.PackageOptions{
PkgTypes: []string{
types.PkgTypeOS,
},
},
},
{
name: "happy path for library packages",
fields: fields{
pkgTypes: "library",
},
want: flag.PackageOptions{
PkgTypes: []string{
types.PkgTypeLibrary,
},
},
},
{
name: "root and indirect relationships",
fields: fields{
pkgRelationships: "root,indirect",
},
want: flag.PackageOptions{
PkgRelationships: []ftypes.Relationship{
ftypes.RelationshipRoot,
ftypes.RelationshipIndirect,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Cleanup(viper.Reset)
setValue(flag.PkgTypesFlag.ConfigName, tt.fields.pkgTypes)
setValue(flag.PkgRelationshipsFlag.ConfigName, tt.fields.pkgRelationships)
// Assert options
f := &flag.PackageFlagGroup{
PkgTypes: flag.PkgTypesFlag.Clone(),
PkgRelationships: flag.PkgRelationshipsFlag.Clone(),
}
got, err := f.ToOptions()
require.NoError(t, err)
assert.EqualExportedValuesf(t, tt.want, got, "PackageFlagGroup")
})
}
}

View File

@@ -106,20 +106,6 @@ var (
ConfigName: "scan.show-suppressed",
Usage: "[EXPERIMENTAL] show suppressed vulnerabilities",
}
PkgTypesFlag = Flag[[]string]{
Name: "pkg-types",
ConfigName: "pkg-types",
Default: types.PkgTypes,
Values: types.PkgTypes,
Usage: "comma-separated list of package types",
Aliases: []Alias{
{
Name: "vuln-type",
ConfigName: "vulnerability.type",
Deprecated: true, // --vuln-type was renamed to --pkg-types
},
},
}
)
// ReportFlagGroup composes common printer flag structs
@@ -139,7 +125,6 @@ type ReportFlagGroup struct {
Severity *Flag[[]string]
Compliance *Flag[string]
ShowSuppressed *Flag[bool]
PkgTypes *Flag[[]string]
}
type ReportOptions struct {
@@ -157,7 +142,6 @@ type ReportOptions struct {
Severities []dbTypes.Severity
Compliance spec.ComplianceSpec
ShowSuppressed bool
PkgTypes []string
}
func NewReportFlagGroup() *ReportFlagGroup {
@@ -176,7 +160,6 @@ func NewReportFlagGroup() *ReportFlagGroup {
Severity: SeverityFlag.Clone(),
Compliance: ComplianceFlag.Clone(),
ShowSuppressed: ShowSuppressedFlag.Clone(),
PkgTypes: PkgTypesFlag.Clone(),
}
}
@@ -200,7 +183,6 @@ func (f *ReportFlagGroup) Flags() []Flagger {
f.Severity,
f.Compliance,
f.ShowSuppressed,
f.PkgTypes,
}
}
@@ -270,7 +252,6 @@ func (f *ReportFlagGroup) ToOptions() (ReportOptions, error) {
Severities: toSeverity(f.Severity.Value()),
Compliance: cs,
ShowSuppressed: f.ShowSuppressed.Value(),
PkgTypes: f.PkgTypes.Value(),
}, nil
}

View File

@@ -160,28 +160,6 @@ func TestReportFlagGroup_ToOptions(t *testing.T) {
Severities: []dbTypes.Severity{dbTypes.SeverityLow},
},
},
{
name: "happy path for OS packages",
fields: fields{
pkgTypes: "os",
},
want: flag.ReportOptions{
PkgTypes: []string{
types.PkgTypeOS,
},
},
},
{
name: "happy path for library packages",
fields: fields{
pkgTypes: "library",
},
want: flag.ReportOptions{
PkgTypes: []string{
types.PkgTypeLibrary,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -206,7 +184,6 @@ func TestReportFlagGroup_ToOptions(t *testing.T) {
setValue(flag.OutputPluginArgFlag.ConfigName, tt.fields.outputPluginArgs)
setValue(flag.SeverityFlag.ConfigName, tt.fields.severities)
setValue(flag.ComplianceFlag.ConfigName, tt.fields.compliance)
setValue(flag.PkgTypesFlag.ConfigName, tt.fields.pkgTypes)
// Assert options
f := &flag.ReportFlagGroup{
@@ -222,7 +199,6 @@ func TestReportFlagGroup_ToOptions(t *testing.T) {
OutputPluginArg: flag.OutputPluginArgFlag.Clone(),
Severity: flag.SeverityFlag.Clone(),
Compliance: flag.ComplianceFlag.Clone(),
PkgTypes: flag.PkgTypesFlag.Clone(),
}
got, err := f.ToOptions()

View File

@@ -96,11 +96,6 @@ var (
Default: "https://rekor.sigstore.dev",
Usage: "[EXPERIMENTAL] address of rekor STL server",
}
IncludeDevDepsFlag = Flag[bool]{
Name: "include-dev-deps",
ConfigName: "scan.include-dev-deps",
Usage: "include development dependencies in the report (supported: npm, yarn)",
}
)
type ScanFlagGroup struct {
@@ -113,7 +108,6 @@ type ScanFlagGroup struct {
Parallel *Flag[int]
SBOMSources *Flag[[]string]
RekorURL *Flag[string]
IncludeDevDeps *Flag[bool]
}
type ScanOptions struct {
@@ -126,7 +120,6 @@ type ScanOptions struct {
Parallel int
SBOMSources []string
RekorURL string
IncludeDevDeps bool
}
func NewScanFlagGroup() *ScanFlagGroup {
@@ -139,7 +132,6 @@ func NewScanFlagGroup() *ScanFlagGroup {
Parallel: ParallelFlag.Clone(),
SBOMSources: SBOMSourcesFlag.Clone(),
RekorURL: RekorURLFlag.Clone(),
IncludeDevDeps: IncludeDevDepsFlag.Clone(),
Slow: SlowFlag.Clone(),
}
}
@@ -159,7 +151,6 @@ func (f *ScanFlagGroup) Flags() []Flagger {
f.Parallel,
f.SBOMSources,
f.RekorURL,
f.IncludeDevDeps,
}
}
@@ -189,6 +180,5 @@ func (f *ScanFlagGroup) ToOptions(args []string) (ScanOptions, error) {
Parallel: parallel,
SBOMSources: f.SBOMSources.Value(),
RekorURL: f.RekorURL.Value(),
IncludeDevDeps: f.IncludeDevDeps.Value(),
}, nil
}

View File

@@ -17,6 +17,13 @@ const (
LevelWarn = slog.LevelWarn
LevelError = slog.LevelError
LevelFatal = slog.Level(12)
PrefixContainerImage = "image"
PrefixPackage = "pkg"
PrefixVulnerability = "vuln"
PrefixMisconfiguration = "misconfig"
PrefixSecret = "secret"
PrefixLicense = "license"
)
// Logger is an alias of slog.Logger

View File

@@ -83,6 +83,7 @@ func (s Scanner) Scan(ctx context.Context, target, artifactKey string, blobKeys
BlobIds: blobKeys,
Options: &rpc.ScanOptions{
PkgTypes: opts.PkgTypes,
PkgRelationships: xstrings.ToStringSlice(opts.PkgRelationships),
Scanners: xstrings.ToStringSlice(opts.Scanners),
LicenseCategories: licenseCategories,
IncludeDevDeps: opts.IncludeDevDeps,

View File

@@ -44,21 +44,7 @@ func teeError(err error) error {
// Scan scans and return response
func (s *ScanServer) Scan(ctx context.Context, in *rpcScanner.ScanRequest) (*rpcScanner.ScanResponse, error) {
scanners := lo.Map(in.Options.Scanners, func(s string, index int) types.Scanner {
return types.Scanner(s)
})
licenseCategories := lo.MapEntries(in.Options.LicenseCategories,
func(k string, v *rpcScanner.Licenses) (ftypes.LicenseCategory, []string) {
return ftypes.LicenseCategory(k), v.Names
})
options := types.ScanOptions{
PkgTypes: in.Options.PkgTypes,
Scanners: scanners,
IncludeDevDeps: in.Options.IncludeDevDeps,
LicenseCategories: licenseCategories,
}
options := s.ToOptions(in.Options)
results, os, err := s.localScanner.Scan(ctx, in.Target, in.ArtifactId, in.BlobIds, options)
if err != nil {
return nil, teeError(xerrors.Errorf("failed scan, %s: %w", in.Target, err))
@@ -67,6 +53,37 @@ func (s *ScanServer) Scan(ctx context.Context, in *rpcScanner.ScanRequest) (*rpc
return rpc.ConvertToRPCScanResponse(results, os), nil
}
func (s *ScanServer) ToOptions(in *rpcScanner.ScanOptions) types.ScanOptions {
pkgRelationships := lo.FilterMap(in.PkgRelationships, func(r string, index int) (ftypes.Relationship, bool) {
rel, err := ftypes.NewRelationship(r)
if err != nil {
log.Warnf("Invalid relationship: %s", r)
return ftypes.RelationshipUnknown, false
}
return rel, true
})
if len(pkgRelationships) == 0 {
pkgRelationships = ftypes.Relationships // For backward compatibility
}
scanners := lo.Map(in.Scanners, func(s string, index int) types.Scanner {
return types.Scanner(s)
})
licenseCategories := lo.MapEntries(in.LicenseCategories,
func(k string, v *rpcScanner.Licenses) (ftypes.LicenseCategory, []string) {
return ftypes.LicenseCategory(k), v.Names
})
return types.ScanOptions{
PkgTypes: in.PkgTypes,
PkgRelationships: pkgRelationships,
Scanners: scanners,
IncludeDevDeps: in.IncludeDevDeps,
LicenseCategories: licenseCategories,
}
}
// CacheServer implements the cache
type CacheServer struct {
cache cache.Cache

View File

@@ -108,9 +108,8 @@ func (s Scanner) Scan(ctx context.Context, targetName, artifactKey string, blobK
func (s Scanner) ScanTarget(ctx context.Context, target types.ScanTarget, options types.ScanOptions) (types.Results, ftypes.OS, error) {
var results types.Results
// By default, we need to remove dev dependencies from the result
// IncludeDevDeps option allows you not to remove them
excludeDevDeps(target.Applications, options.IncludeDevDeps)
// Filter packages according to the options
excludePackages(&target, options)
// Add packages if needed and scan packages for vulnerabilities
vulnResults, eosl, err := s.scanVulnerabilities(ctx, target, options)
@@ -395,6 +394,32 @@ func ShouldScanMisconfigOrRbac(scanners types.Scanners) bool {
return scanners.AnyEnabled(types.MisconfigScanner, types.RBACScanner)
}
func excludePackages(target *types.ScanTarget, options types.ScanOptions) {
// Filter packages by relationship
filterPkgByRelationship(target, options)
// By default, development packages are removed from the result
// '--include-dev-deps' option allows including them
excludeDevDeps(target.Applications, options.IncludeDevDeps)
}
func filterPkgByRelationship(target *types.ScanTarget, options types.ScanOptions) {
if slices.Compare(options.PkgRelationships, ftypes.Relationships) == 0 {
return // No need to filter
}
filter := func(pkgs []ftypes.Package) []ftypes.Package {
return lo.Filter(pkgs, func(pkg ftypes.Package, index int) bool {
return slices.Contains(options.PkgRelationships, pkg.Relationship)
})
}
target.Packages = filter(target.Packages)
for i, app := range target.Applications {
target.Applications[i].Packages = filter(app.Packages)
}
}
// excludeDevDeps removes development dependencies from the list of applications
func excludeDevDeps(apps []ftypes.Application, include bool) {
if include {

View File

@@ -67,6 +67,15 @@ var (
laravelPkg = ftypes.Package{
Name: "laravel/framework",
Version: "6.0.0",
Relationship: ftypes.RelationshipDirect,
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
}
guzzlePkg = ftypes.Package{
Name: "guzzlehttp/guzzle",
Version: "7.9.2",
Relationship: ftypes.RelationshipIndirect,
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
@@ -98,6 +107,7 @@ func TestScanner_Scan(t *testing.T) {
types.PkgTypeOS,
types.PkgTypeLibrary,
},
PkgRelationships: ftypes.Relationships,
Scanners: types.Scanners{types.VulnerabilityScanner},
},
},
@@ -198,6 +208,7 @@ func TestScanner_Scan(t *testing.T) {
target: "alpine:latest",
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{
PkgRelationships: ftypes.Relationships,
Scanners: types.Scanners{types.LicenseScanner},
},
},
@@ -298,6 +309,7 @@ func TestScanner_Scan(t *testing.T) {
types.PkgTypeOS,
types.PkgTypeLibrary,
},
PkgRelationships: ftypes.Relationships,
Scanners: types.Scanners{types.VulnerabilityScanner},
},
},
@@ -378,6 +390,7 @@ func TestScanner_Scan(t *testing.T) {
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{
PkgTypes: []string{types.PkgTypeLibrary},
PkgRelationships: ftypes.Relationships,
Scanners: types.Scanners{types.VulnerabilityScanner},
},
},
@@ -477,6 +490,7 @@ func TestScanner_Scan(t *testing.T) {
types.PkgTypeOS,
types.PkgTypeLibrary,
},
PkgRelationships: ftypes.Relationships,
Scanners: types.Scanners{types.VulnerabilityScanner},
},
},
@@ -558,6 +572,7 @@ func TestScanner_Scan(t *testing.T) {
types.PkgTypeOS,
types.PkgTypeLibrary,
},
PkgRelationships: ftypes.Relationships,
Scanners: types.Scanners{types.VulnerabilityScanner},
},
},
@@ -630,6 +645,7 @@ func TestScanner_Scan(t *testing.T) {
types.PkgTypeOS,
types.PkgTypeLibrary,
},
PkgRelationships: ftypes.Relationships,
Scanners: types.Scanners{types.VulnerabilityScanner},
},
},
@@ -645,12 +661,17 @@ func TestScanner_Scan(t *testing.T) {
wantResults: nil,
},
{
name: "happy path with only language-specific package detection",
name: "happy path with only language-specific package detection, excluding direct packages",
args: args{
target: "alpine:latest",
layerIDs: []string{"sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33"},
options: types.ScanOptions{
PkgTypes: []string{types.PkgTypeLibrary},
PkgRelationships: []ftypes.Relationship{
ftypes.RelationshipUnknown,
ftypes.RelationshipRoot,
ftypes.RelationshipIndirect,
},
Scanners: types.Scanners{types.VulnerabilityScanner},
},
},
@@ -680,7 +701,8 @@ func TestScanner_Scan(t *testing.T) {
Type: "composer",
FilePath: "/app/composer-lock.json",
Packages: []ftypes.Package{
laravelPkg,
laravelPkg, // will be excluded
guzzlePkg,
},
},
},
@@ -721,19 +743,7 @@ func TestScanner_Scan(t *testing.T) {
Target: "/app/composer-lock.json",
Class: types.ClassLangPkg,
Type: ftypes.Composer,
Packages: ftypes.Packages{laravelPkg},
Vulnerabilities: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2021-21263",
PkgName: laravelPkg.Name,
InstalledVersion: laravelPkg.Version,
FixedVersion: "8.22.1, 7.30.3, 6.20.12",
Status: dbTypes.StatusFixed,
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
},
},
Packages: ftypes.Packages{guzzlePkg},
},
},
wantOS: ftypes.OS{
@@ -900,6 +910,7 @@ func TestScanner_Scan(t *testing.T) {
types.PkgTypeOS,
types.PkgTypeLibrary,
},
PkgRelationships: ftypes.Relationships,
Scanners: types.Scanners{types.VulnerabilityScanner},
},
},
@@ -921,6 +932,7 @@ func TestScanner_Scan(t *testing.T) {
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{
PkgTypes: []string{types.PkgTypeLibrary},
PkgRelationships: ftypes.Relationships,
Scanners: types.Scanners{types.VulnerabilityScanner},
},
},
@@ -1103,8 +1115,7 @@ func TestScanner_Scan(t *testing.T) {
s := NewScanner(applier, ospkg.NewScanner(), langpkg.NewScanner(), vulnerability.NewClient(db.Config{}))
gotResults, gotOS, err := s.Scan(context.Background(), tt.args.target, "", tt.args.layerIDs, tt.args.options)
if tt.wantErr != "" {
require.Error(t, err, tt.name)
require.Contains(t, err.Error(), tt.wantErr, tt.name)
require.ErrorContains(t, err, tt.wantErr, tt.name)
return
}

View File

@@ -23,6 +23,7 @@ type ScanTarget struct {
// ScanOptions holds the attributes for scanning vulnerabilities
type ScanOptions struct {
PkgTypes []string
PkgRelationships []types.Relationship
Scanners Scanners
ImageConfigScanners Scanners // Scanners for container image configuration
ScanRemovedPackages bool

View File

@@ -1,17 +1,28 @@
package strings
import "github.com/samber/lo"
import (
"fmt"
"github.com/samber/lo"
)
type String interface {
~string
}
func ToStringSlice[T String](ss []T) []string {
if ss == nil {
func ToStringSlice[T any](ss []T) []string {
if len(ss) == 0 {
return nil
}
return lo.Map(ss, func(s T, _ int) string {
return string(s)
switch v := any(s).(type) {
case string:
return v
case fmt.Stringer:
return v.String()
default:
return fmt.Sprint(v)
}
})
}

View File

@@ -150,6 +150,7 @@ type ScanOptions struct {
Scanners []string `protobuf:"bytes,2,rep,name=scanners,proto3" json:"scanners,omitempty"`
LicenseCategories map[string]*Licenses `protobuf:"bytes,4,rep,name=license_categories,json=licenseCategories,proto3" json:"license_categories,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
IncludeDevDeps bool `protobuf:"varint,5,opt,name=include_dev_deps,json=includeDevDeps,proto3" json:"include_dev_deps,omitempty"`
PkgRelationships []string `protobuf:"bytes,6,rep,name=pkg_relationships,json=pkgRelationships,proto3" json:"pkg_relationships,omitempty"`
}
func (x *ScanOptions) Reset() {
@@ -212,6 +213,13 @@ func (x *ScanOptions) GetIncludeDevDeps() bool {
return false
}
func (x *ScanOptions) GetPkgRelationships() []string {
if x != nil {
return x.PkgRelationships
}
return nil
}
type ScanResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -398,7 +406,7 @@ var file_rpc_scanner_service_proto_rawDesc = []byte{
0x53, 0x63, 0x61, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x22, 0x20, 0x0a, 0x08, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73,
0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52,
0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xbd, 0x02, 0x0a, 0x0b, 0x53, 0x63, 0x61, 0x6e, 0x4f,
0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xea, 0x02, 0x0a, 0x0b, 0x53, 0x63, 0x61, 0x6e, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6b, 0x67, 0x5f, 0x74, 0x79,
0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6b, 0x67, 0x54, 0x79,
0x70, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x18,
@@ -411,59 +419,61 @@ var file_rpc_scanner_service_proto_rawDesc = []byte{
0x79, 0x52, 0x11, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f,
0x72, 0x69, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f,
0x64, 0x65, 0x76, 0x5f, 0x64, 0x65, 0x70, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e,
0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x44, 0x65, 0x76, 0x44, 0x65, 0x70, 0x73, 0x1a, 0x60,
0x0a, 0x16, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72,
0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x69, 0x76,
0x79, 0x2e, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x63,
0x65, 0x6e, 0x73, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x64, 0x0a, 0x0c, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
0x6e, 0x2e, 0x4f, 0x53, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x32, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75,
0x6c, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x69, 0x76,
0x79, 0x2e, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73,
0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0xd5, 0x03, 0x0a,
0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65,
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12,
0x45, 0x0a, 0x0f, 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69,
0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62,
0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0f, 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69,
0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x54, 0x0a, 0x11, 0x6d, 0x69, 0x73, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x26, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x6d, 0x69, 0x73, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05,
0x63, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6c, 0x61,
0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52,
0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x47, 0x0a, 0x10, 0x63, 0x75, 0x73,
0x74, 0x6f, 0x6d, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x52, 0x0f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x73, 0x12, 0x35, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x18, 0x08, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67,
0x52, 0x07, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x08, 0x6c, 0x69, 0x63,
0x65, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x72,
0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x74, 0x65, 0x63,
0x74, 0x65, 0x64, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x6c, 0x69, 0x63, 0x65,
0x6e, 0x73, 0x65, 0x73, 0x32, 0x50, 0x0a, 0x07, 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12,
0x45, 0x0a, 0x04, 0x53, 0x63, 0x61, 0x6e, 0x12, 0x1d, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e,
0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73,
0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x71, 0x75, 0x61, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
0x79, 0x2f, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x63, 0x61, 0x6e,
0x6e, 0x65, 0x72, 0x3b, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x44, 0x65, 0x76, 0x44, 0x65, 0x70, 0x73, 0x12, 0x2b,
0x0a, 0x11, 0x70, 0x6b, 0x67, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68,
0x69, 0x70, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x70, 0x6b, 0x67, 0x52, 0x65,
0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x1a, 0x60, 0x0a, 0x16, 0x4c,
0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73,
0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73,
0x65, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08,
0x03, 0x10, 0x04, 0x22, 0x64, 0x0a, 0x0c, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x10, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4f,
0x53, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x32, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73,
0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73,
0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74,
0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0xd5, 0x03, 0x0a, 0x06, 0x52, 0x65,
0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x45, 0x0a, 0x0f,
0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18,
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69,
0x74, 0x79, 0x52, 0x0f, 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74,
0x69, 0x65, 0x73, 0x12, 0x54, 0x0a, 0x11, 0x6d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26,
0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65,
0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x6d, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6c, 0x61,
0x73, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x12,
0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74,
0x79, 0x70, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18,
0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x08, 0x70, 0x61,
0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x47, 0x0a, 0x10, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x1c, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0f,
0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12,
0x35, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73,
0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x08, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73,
0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64,
0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65,
0x73, 0x32, 0x50, 0x0a, 0x07, 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x45, 0x0a, 0x04,
0x53, 0x63, 0x61, 0x6e, 0x12, 0x1d, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, 0x63, 0x61,
0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x73, 0x63, 0x61, 0x6e,
0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x61, 0x71, 0x75, 0x61, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74,
0x72, 0x69, 0x76, 0x79, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72,
0x3b, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@@ -27,6 +27,7 @@ message ScanOptions {
repeated string scanners = 2;
map<string, Licenses> license_categories = 4;
bool include_dev_deps = 5;
repeated string pkg_relationships = 6;
reserved 3; // deleted 'list_all_packages'
}

View File

@@ -1094,46 +1094,47 @@ func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error)
}
var twirpFileDescriptor0 = []byte{
// 650 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x54, 0xcd, 0x6e, 0xdb, 0x38,
0x10, 0x86, 0x7f, 0x62, 0xcb, 0xe3, 0xc5, 0xc6, 0x21, 0x76, 0x03, 0xc5, 0xd9, 0x6c, 0x0d, 0x1f,
0x0a, 0x9f, 0xec, 0xc6, 0x69, 0xd1, 0xbf, 0x5b, 0x93, 0xb4, 0x48, 0xd1, 0x22, 0x01, 0x1d, 0xf4,
0xd0, 0x8b, 0x4b, 0x53, 0x13, 0x95, 0xb0, 0x2c, 0x29, 0x1c, 0xca, 0x80, 0x5f, 0xa5, 0xef, 0xd2,
0xc7, 0xe8, 0xfb, 0x14, 0x22, 0x25, 0x23, 0x76, 0x92, 0x9e, 0xc4, 0x99, 0xf9, 0xe6, 0x9b, 0x0f,
0x9c, 0x4f, 0x84, 0x03, 0x9d, 0xca, 0x11, 0x49, 0x11, 0xc7, 0xa8, 0x47, 0x84, 0x7a, 0xa9, 0x24,
0x0e, 0x53, 0x9d, 0x98, 0x84, 0x75, 0x8c, 0x56, 0xcb, 0xd5, 0xb0, 0x28, 0x0e, 0x97, 0xc7, 0x5d,
0x3f, 0x07, 0xcb, 0x64, 0xb1, 0x48, 0xe2, 0x4d, 0x6c, 0xff, 0x47, 0x05, 0xda, 0x13, 0x29, 0x62,
0x8e, 0xb7, 0x19, 0x92, 0x61, 0xfb, 0xd0, 0x30, 0x42, 0x87, 0x68, 0xfc, 0x4a, 0xaf, 0x32, 0x68,
0xf1, 0x22, 0x62, 0x4f, 0xa0, 0x2d, 0xb4, 0x51, 0x37, 0x42, 0x9a, 0xa9, 0x0a, 0xfc, 0xaa, 0x2d,
0x42, 0x99, 0xba, 0x08, 0xd8, 0x01, 0x78, 0xb3, 0x28, 0x99, 0x4d, 0x55, 0x40, 0x7e, 0xad, 0x57,
0x1b, 0xb4, 0x78, 0x33, 0x8f, 0x2f, 0x02, 0x62, 0x2f, 0xa1, 0x99, 0xa4, 0x46, 0x25, 0x31, 0xf9,
0xf5, 0x5e, 0x65, 0xd0, 0x1e, 0x1f, 0x0d, 0xb7, 0x15, 0x0e, 0x73, 0x0d, 0x97, 0x0e, 0xc4, 0x4b,
0x74, 0xbf, 0x07, 0xde, 0x27, 0x25, 0x31, 0x26, 0x24, 0xf6, 0x0f, 0xec, 0xc4, 0x62, 0x81, 0xe4,
0x57, 0x2c, 0xb9, 0x0b, 0xfa, 0x3f, 0xab, 0x4e, 0x7e, 0xd1, 0xca, 0x0e, 0xa1, 0x95, 0xce, 0xc3,
0xa9, 0x59, 0xa5, 0x6b, 0xa4, 0x97, 0xce, 0xc3, 0xeb, 0x3c, 0x66, 0x5d, 0xf0, 0x8a, 0x89, 0xe4,
0x57, 0x5d, 0xad, 0x8c, 0x99, 0x04, 0x16, 0xb9, 0x51, 0x53, 0x29, 0x0c, 0x86, 0x89, 0x56, 0x98,
0xcb, 0xad, 0x0d, 0xda, 0xe3, 0xe7, 0x7f, 0x94, 0x3b, 0x2c, 0x24, 0x9e, 0xae, 0xdb, 0xce, 0x63,
0xa3, 0x57, 0x7c, 0x2f, 0xda, 0xce, 0xb3, 0x01, 0x74, 0x54, 0x2c, 0xa3, 0x2c, 0xc0, 0x69, 0x80,
0xcb, 0x69, 0x80, 0x29, 0xf9, 0x3b, 0xbd, 0xca, 0xc0, 0xe3, 0x7f, 0x17, 0xf9, 0x33, 0x5c, 0x9e,
0x61, 0x4a, 0xdd, 0x6f, 0xb0, 0xff, 0x30, 0x2d, 0xeb, 0x40, 0x6d, 0x8e, 0xab, 0x62, 0x3b, 0xf9,
0x91, 0x3d, 0x83, 0x9d, 0xa5, 0x88, 0x32, 0xb4, 0x4b, 0x69, 0x8f, 0xbb, 0xf7, 0xd5, 0x96, 0x97,
0xc8, 0x1d, 0xf0, 0x4d, 0xf5, 0x55, 0xe5, 0x63, 0xdd, 0xab, 0x75, 0xea, 0xfd, 0x00, 0xfe, 0x72,
0xdb, 0xa7, 0x34, 0x89, 0x09, 0x59, 0x0f, 0xaa, 0x09, 0x59, 0xf2, 0xf6, 0xb8, 0x53, 0x10, 0x39,
0xdf, 0x0c, 0x2f, 0x27, 0xbc, 0x9a, 0x10, 0x1b, 0x43, 0x53, 0x23, 0x65, 0x91, 0x71, 0x6b, 0x6e,
0x8f, 0xfd, 0xfb, 0xf3, 0xb8, 0x05, 0xf0, 0x12, 0xd8, 0xff, 0x55, 0x83, 0x86, 0xcb, 0x3d, 0xea,
0xaf, 0x73, 0xd8, 0x5d, 0x66, 0x51, 0x8c, 0x5a, 0xcc, 0x54, 0xa4, 0x4c, 0x7e, 0xf9, 0x55, 0x4b,
0x7f, 0xb8, 0xa9, 0xe2, 0xcb, 0x1d, 0xd0, 0x8a, 0x6f, 0xf7, 0xb0, 0x6b, 0xd8, 0x5b, 0x28, 0x92,
0x49, 0x7c, 0xa3, 0xc2, 0x4c, 0x8b, 0xd2, 0x74, 0x39, 0xd1, 0xd3, 0x4d, 0xa2, 0x33, 0x34, 0x28,
0x0d, 0x06, 0x9f, 0xb7, 0xe0, 0xfc, 0x3e, 0x41, 0xee, 0x3d, 0x19, 0x09, 0x22, 0xbf, 0x61, 0x35,
0xbb, 0x80, 0x31, 0xa8, 0xe7, 0x3e, 0xf3, 0x6b, 0x36, 0x69, 0xcf, 0xec, 0x18, 0xbc, 0x54, 0xc8,
0xb9, 0x08, 0x31, 0xdf, 0x6c, 0x3e, 0xf6, 0xdf, 0xcd, 0xb1, 0x57, 0xae, 0xca, 0xd7, 0x30, 0xf6,
0x01, 0x3a, 0x32, 0x23, 0x93, 0x2c, 0xa6, 0x1a, 0x29, 0xc9, 0xb4, 0x44, 0xf2, 0x9b, 0xb6, 0xf5,
0xbf, 0xcd, 0xd6, 0x53, 0x8b, 0xe2, 0x05, 0x88, 0xef, 0xca, 0x8d, 0x98, 0xd8, 0x0b, 0x68, 0x12,
0x4a, 0x8d, 0x86, 0x7c, 0xef, 0xa1, 0xab, 0x9b, 0xd8, 0xe2, 0x7b, 0x15, 0x07, 0x2a, 0x0e, 0x79,
0x89, 0x65, 0xaf, 0xc1, 0x2b, 0x9c, 0x4a, 0x7e, 0xcb, 0xf6, 0x1d, 0x3d, 0x7c, 0x53, 0x85, 0x8b,
0xf8, 0x1a, 0x3e, 0xbe, 0x82, 0xe6, 0xc4, 0x6d, 0x9d, 0x9d, 0x43, 0x3d, 0x3f, 0xb2, 0x47, 0x7e,
0xed, 0xe2, 0x79, 0xe9, 0xfe, 0xff, 0x58, 0xd9, 0xf9, 0xef, 0xdd, 0xc9, 0xd7, 0xe3, 0x50, 0x99,
0xef, 0xd9, 0x2c, 0x1f, 0x3e, 0x12, 0xb7, 0x99, 0x20, 0x94, 0x99, 0x56, 0x66, 0x35, 0xb2, 0x8d,
0xa3, 0x3b, 0xaf, 0xde, 0xdb, 0xe2, 0x3b, 0x6b, 0xd8, 0xa7, 0xec, 0xe4, 0x77, 0x00, 0x00, 0x00,
0xff, 0xff, 0x50, 0x58, 0x22, 0xc7, 0x13, 0x05, 0x00, 0x00,
// 671 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x54, 0xdd, 0x6e, 0xd3, 0x4c,
0x10, 0x55, 0x7e, 0x9a, 0x38, 0x93, 0x4f, 0x5f, 0xd3, 0x15, 0x54, 0x6e, 0x4a, 0x21, 0xca, 0x05,
0x8a, 0x84, 0x94, 0xd0, 0x14, 0xc4, 0xdf, 0x1d, 0x6d, 0x41, 0x45, 0xa0, 0x56, 0x9b, 0x8a, 0x0b,
0x6e, 0xc2, 0x66, 0x3d, 0x75, 0x57, 0x71, 0x6c, 0x77, 0x67, 0x1d, 0x29, 0xaf, 0xc2, 0x7b, 0xf1,
0x12, 0x3c, 0x05, 0xda, 0xb5, 0x13, 0x35, 0x69, 0xcb, 0x95, 0x77, 0x66, 0xce, 0xcc, 0x39, 0xde,
0x39, 0x5a, 0xd8, 0xd3, 0xa9, 0x1c, 0x90, 0x14, 0x71, 0x8c, 0x7a, 0x40, 0xa8, 0xe7, 0x4a, 0x62,
0x3f, 0xd5, 0x89, 0x49, 0x58, 0xcb, 0x68, 0x35, 0x5f, 0xf4, 0x8b, 0x62, 0x7f, 0x7e, 0xd8, 0xf6,
0x2d, 0x58, 0x26, 0xb3, 0x59, 0x12, 0xaf, 0x63, 0xbb, 0xbf, 0x4a, 0xd0, 0x1c, 0x49, 0x11, 0x73,
0xbc, 0xc9, 0x90, 0x0c, 0xdb, 0x85, 0x9a, 0x11, 0x3a, 0x44, 0xe3, 0x97, 0x3a, 0xa5, 0x5e, 0x83,
0x17, 0x11, 0x7b, 0x06, 0x4d, 0xa1, 0x8d, 0xba, 0x12, 0xd2, 0x8c, 0x55, 0xe0, 0x97, 0x5d, 0x11,
0x96, 0xa9, 0xb3, 0x80, 0xed, 0x81, 0x37, 0x89, 0x92, 0xc9, 0x58, 0x05, 0xe4, 0x57, 0x3a, 0x95,
0x5e, 0x83, 0xd7, 0x6d, 0x7c, 0x16, 0x10, 0x7b, 0x03, 0xf5, 0x24, 0x35, 0x2a, 0x89, 0xc9, 0xaf,
0x76, 0x4a, 0xbd, 0xe6, 0xf0, 0xa0, 0xbf, 0xa9, 0xb0, 0x6f, 0x35, 0x9c, 0xe7, 0x20, 0xbe, 0x44,
0x77, 0x3b, 0xe0, 0x7d, 0x55, 0x12, 0x63, 0x42, 0x62, 0x8f, 0x60, 0x2b, 0x16, 0x33, 0x24, 0xbf,
0xe4, 0x86, 0xe7, 0x41, 0xf7, 0x4f, 0x39, 0x97, 0x5f, 0xb4, 0xb2, 0x7d, 0x68, 0xa4, 0xd3, 0x70,
0x6c, 0x16, 0xe9, 0x0a, 0xe9, 0xa5, 0xd3, 0xf0, 0xd2, 0xc6, 0xac, 0x0d, 0x5e, 0xc1, 0x48, 0x7e,
0x39, 0xaf, 0x2d, 0x63, 0x26, 0x81, 0x45, 0x39, 0xd5, 0x58, 0x0a, 0x83, 0x61, 0xa2, 0x15, 0x5a,
0xb9, 0x95, 0x5e, 0x73, 0xf8, 0xea, 0x9f, 0x72, 0xfb, 0x85, 0xc4, 0xe3, 0x55, 0xdb, 0x69, 0x6c,
0xf4, 0x82, 0xef, 0x44, 0x9b, 0x79, 0xd6, 0x83, 0x96, 0x8a, 0x65, 0x94, 0x05, 0x38, 0x0e, 0x70,
0x3e, 0x0e, 0x30, 0x25, 0x7f, 0xab, 0x53, 0xea, 0x79, 0xfc, 0xff, 0x22, 0x7f, 0x82, 0xf3, 0x13,
0x4c, 0x89, 0xbd, 0x80, 0x1d, 0xfb, 0x1f, 0x1a, 0x23, 0xe1, 0x48, 0xae, 0x55, 0x4a, 0x7e, 0xcd,
0x69, 0x6e, 0xa5, 0xd3, 0x90, 0xdf, 0xce, 0xb7, 0x7f, 0xc2, 0xee, 0xfd, 0x1a, 0x58, 0x0b, 0x2a,
0x53, 0x5c, 0x14, 0xab, 0xb4, 0x47, 0xf6, 0x12, 0xb6, 0xe6, 0x22, 0xca, 0xd0, 0x6d, 0xb0, 0x39,
0x6c, 0xdf, 0xfd, 0xb5, 0xe5, 0x8d, 0xf3, 0x1c, 0xf8, 0xbe, 0xfc, 0xb6, 0xf4, 0xa5, 0xea, 0x55,
0x5a, 0xd5, 0x6e, 0x00, 0xff, 0xe5, 0x56, 0xa1, 0x34, 0x89, 0x09, 0x59, 0x07, 0xca, 0x09, 0xb9,
0xe1, 0xcd, 0x61, 0xab, 0x18, 0x94, 0x9b, 0xac, 0x7f, 0x3e, 0xe2, 0xe5, 0x84, 0xd8, 0x10, 0xea,
0x1a, 0x29, 0x8b, 0x4c, 0xee, 0x89, 0xe6, 0xd0, 0xbf, 0xcb, 0xc7, 0x1d, 0x80, 0x2f, 0x81, 0xdd,
0xdf, 0x15, 0xa8, 0xe5, 0xb9, 0x07, 0xcd, 0x78, 0x0a, 0xdb, 0xf3, 0x2c, 0x8a, 0x51, 0x8b, 0x89,
0x8a, 0x94, 0xb1, 0x9b, 0x2a, 0xbb, 0xf1, 0xfb, 0xeb, 0x2a, 0xbe, 0xdf, 0x02, 0x2d, 0xf8, 0x66,
0x0f, 0xbb, 0x84, 0x9d, 0x99, 0x22, 0x99, 0xc4, 0x57, 0x2a, 0xcc, 0xb4, 0x58, 0x3a, 0xd4, 0x0e,
0x7a, 0xbe, 0x3e, 0xe8, 0x04, 0x0d, 0x4a, 0x83, 0xc1, 0xb7, 0x0d, 0x38, 0xbf, 0x3b, 0xc0, 0x1a,
0x55, 0x46, 0x82, 0xec, 0xba, 0xac, 0xe6, 0x3c, 0x60, 0x0c, 0xaa, 0xd6, 0x94, 0x7e, 0xc5, 0x25,
0xdd, 0x99, 0x1d, 0x82, 0x97, 0x0a, 0x39, 0x15, 0x21, 0x5a, 0x1b, 0x58, 0xda, 0xc7, 0xeb, 0xb4,
0x17, 0x79, 0x95, 0xaf, 0x60, 0xec, 0x33, 0xb4, 0x64, 0x46, 0x26, 0x99, 0x8d, 0x35, 0x52, 0x92,
0x69, 0x89, 0xe4, 0xd7, 0x5d, 0xeb, 0x93, 0xf5, 0xd6, 0x63, 0x87, 0xe2, 0x05, 0x88, 0x6f, 0xcb,
0xb5, 0x98, 0xd8, 0x6b, 0xa8, 0x13, 0x4a, 0x8d, 0x86, 0x7c, 0xef, 0xbe, 0xab, 0x1b, 0xb9, 0xe2,
0x27, 0x15, 0x07, 0x2a, 0x0e, 0xf9, 0x12, 0xcb, 0xde, 0x81, 0x57, 0xd8, 0x9a, 0xfc, 0x86, 0xeb,
0x3b, 0xb8, 0xff, 0xa6, 0x0a, 0x17, 0xf1, 0x15, 0x7c, 0x78, 0x01, 0xf5, 0x51, 0xbe, 0x75, 0x76,
0x0a, 0x55, 0x7b, 0x64, 0x0f, 0xbc, 0x03, 0xc5, 0x5b, 0xd4, 0x7e, 0xfa, 0x50, 0x39, 0xf7, 0xdf,
0xc7, 0xa3, 0x1f, 0x87, 0xa1, 0x32, 0xd7, 0xd9, 0xc4, 0x92, 0x0f, 0xc4, 0x4d, 0x26, 0x08, 0x65,
0xa6, 0x95, 0x59, 0x0c, 0x5c, 0xe3, 0xe0, 0xd6, 0x13, 0xf9, 0xa1, 0xf8, 0x4e, 0x6a, 0xee, 0xdd,
0x3b, 0xfa, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x66, 0x86, 0x78, 0x40, 0x05, 0x00, 0x00,
}